[英]Add Type Level Natural Numbers
我假設,不可能在haskell中添加兩個類型級自然數。 這是真的?
假設自然數的定義如下:
class HNat a
data HZero
instance HNat HZero
data HSucc n
instance (HNat n) => HNat (HSucc n)
以類似於以下的方式定義HAdd是否合適:
class (HNat n1, HNat n2, HNat ne) => HAdd n1 n2 ne | n1 n2 -> ne
instance HAdd HZero HZero HZero
instance (HNat x) => HAdd HZero x x
instance (HNat n1
,HNat x) => HAdd (HSucc n1) x (HAdd n1 (HSucc x) (???))
您不需要添加HZero
和HZero
。 第二種情況已經涵蓋了這一點。 想想你如何通過對第一個參數的歸納,在術語水平上添加Peano自然:
data Nat = Zero | Succ Nat
add :: Nat -> Nat -> Nat
add Zero y = y
add (Succ x) y = Succ (add x y)
現在,如果您正在使用函數依賴項,那么您正在編寫邏輯程序。 因此,不是在右側進行遞歸調用,而是在左側為遞歸調用的結果添加約束:
class (HNat x, HNat y, HNat r) => HAdd x y r | x y -> r
instance (HNat y) => HAdd HZero y y
instance (HAdd x y r) => HAdd (HSucc x) y (HSucc r)
您不需要第二個實例中的HNat
約束。 它們隱含在類的超類約束上。
這些天,我認為進行這種類型級編程的最好方法是使用DataKinds
和TypeFamilies
。 您在術語級別定義:
data Nat = Zero | Succ Nat
然后你可以使用Nat
作為一種類型,也可以作為一種類型 。 然后,您可以在兩個自然數上定義類型系列,如下所示:
type family Add (x :: Nat) (y :: Nat) :: Nat
type instance Add Zero y = y
type instance Add (Succ x) y = Succ (Add x y)
這更接近於添加的術語級定義。 此外,使用“提升”類Nat
可以使您不必定義諸如HNat
類的類。
有可能的。 看一下package type-level-natural-number
和`type-level-natural-number-operations
。 兩者都有點舊,但易於使用,后者定義了Plus
類型。
無論如何,我會改變你的最后一行到這樣的東西(我沒有測試這是否編譯)。
instance (HNat n1, HNat x, HAdd n1 x y) => HAdd (HSucc n1) x (HAdd n1 x (HSucc y))
基本上,您所做的是以歸納方式定義加法,並且附加約束HAdd n1 xy
添加必要的歸納情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.