【发布时间】:2015-04-23 12:21:57
【问题描述】:
我正在尝试在 Haskell 中为固定长度的列表定义一种类型。当我使用标准方法将自然数编码为一元类型时,一切正常。但是,当我尝试在 GHC 的类型文字上构建所有内容时,我遇到了很多问题。
我对所需列表类型的第一次尝试是
data List (n :: Nat) a where
Nil :: List 0 a
(:>) :: a -> List n a -> List (n+1) a
不幸的是,它不允许使用 type 编写 zip 函数
zip :: List n a -> List n b -> List n (a,b)
我可以通过将(:>)类型的类型变量n减1来解决这个问题:
data List (n :: Nat) a where
Nil :: List 0 a
(:>) :: a -> List (n-1) a -> List n a -- subtracted 1 from both n's
接下来,我尝试定义一个追加函数:
append :: List n1 a -> List n2 a -> List (n1 + n2) a
append Nil ys = ys
append (x :> xs) ys = x :> (append xs ys)
不幸的是,GHC 告诉我
Couldn't match type ‘(n1 + n2) - 1’ with ‘(n1 - 1) + n2’
将约束 ((n1 + n2) - 1) ~ ((n1 - 1) + n2) 添加到签名并不能解决问题,因为 GHC 抱怨
Could not deduce ((((n1 - 1) - 1) + n2) ~ (((n1 + n2) - 1) - 1))
from the context (((n1 + n2) - 1) ~ ((n1 - 1) + n2))
现在,我显然陷入了某种无限循环。
所以,我想知道是否可以使用类型文字为固定长度的列表定义一个类型。我是否可能正是为了这个目的而监督图书馆?基本上,唯一的要求是我想写类似List 3 a 而不是List (S (S (S Z))) a。
【问题讨论】:
-
您可以在 Hasochism 论文中找到关于类型级向量长度相关问题的一些讨论:personal.cis.strath.ac.uk/conor.mcbride/pub/hasochism.pdf
-
“Hasochism”听起来很诱人。尽管如此,我还是会试一试这篇论文。谢谢。
-
在带有
Nat的普通列表周围创建一个新类型的包装器可能更容易,类似于Linear.V的做法。您可以在一个模块中定义一些原语并隐藏构造函数以确保一切安全。
标签: haskell ghc type-inference