Haskell 具有静态类型长度的列表的写入长度函数
给定一个静态类型长度的列表(以示例为例): 是否可以编写一个长度函数,使用静态类型而不是通常的递归来计算长度 到目前为止,我的努力使我得出结论,这是不可能的,因为需要“取消”类型信息才能在其上重现:Haskell 具有静态类型长度的列表的写入长度函数,haskell,types,Haskell,Types,给定一个静态类型长度的列表(以示例为例): 是否可以编写一个长度函数,使用静态类型而不是通常的递归来计算长度 到目前为止,我的努力使我得出结论,这是不可能的,因为需要“取消”类型信息才能在其上重现: class HasLength a where length :: a -> Natural instance HasLength (List el Zero) where length _ = 0 instance HasLength (List el (Succ len
class HasLength a where
length :: a -> Natural
instance HasLength (List el Zero) where
length _ = 0
instance HasLength (List el (Succ len)) where
length _ = 1 + *how to recur on type of len*
然而,我才刚刚开始了解类型可能具有的所有魔力,因此我知道我无法构思解决方案并不意味着没有解决方案
更新
由于length返回自然值,因此我错误地编写了length\uu=1+…
。正确的例子(使用下面给出的答案)是
例如:
instance HasLength (List el len) => HasLength (List el (Succ len)) where
length _ = 1 + length (undefined :: List el len)
注意:这需要
ScopedTypeVariables
扩展名 如果您使用数据种类
扩展,这将更加容易,它将允许您将自然
升级为一种类型,从而使(升级的)类型Zero
和succn
更易于处理,并消除像succchar
这样的废话。有几种方法可以做到这一点,但要紧跟文本:
{-#LANGUAGE GADTs, DataKinds, StandaloneDeriving #-}
data Natural = Zero | Succ Natural deriving (Show,Eq,Ord)
data List el len where
Nil :: List el Zero
Cons :: el -> List el len -> List el (Succ len)
deriving instance Show el => Show (List el len)
class HasLength f where len :: f n -> Natural
instance HasLength (List el) where
len Nil = Zero
len (Cons _ xs) = Succ (len xs)
(我还使用了
StandaloneDeriving
,在这种情况下需要自动派生Show
。谢谢应用,你说得对;这要干净得多。但是,当我尝试运行它时,我得到了以下结果:Kind不匹配HasLength的第一个参数应该有Kind*->*,但是List el在HasLength(List el)的实例声明中有Kind Natural->*,我恐怕不知道对此的适当修复方法。指定HasLength的参数应该具有kindNatural->*
似乎会使它变得不必要的特定,但我不确定。有什么建议吗?:)嗯,可能是ghc版本——这些东西是ghc-7.4之后的新东西。也许我错过了什么。您可以向HasLength
中添加一个专门化它的种类签名。但是这个——对于长度索引列表和常规haskell列表的实例,无论是ghc-7.4还是ghc-7.6 Aha,都可以运行良好,您的hpaste清除了它。我缺少各种各样的布拉格语。谢谢!
instance HasLength (List el len) => HasLength (List el (Succ len)) where
length _ = 1 + length (undefined :: List el len)
{-#LANGUAGE GADTs, DataKinds, StandaloneDeriving #-}
data Natural = Zero | Succ Natural deriving (Show,Eq,Ord)
data List el len where
Nil :: List el Zero
Cons :: el -> List el len -> List el (Succ len)
deriving instance Show el => Show (List el len)
class HasLength f where len :: f n -> Natural
instance HasLength (List el) where
len Nil = Zero
len (Cons _ xs) = Succ (len xs)