将列表转换为类型安全的向量

时间:2014-05-30 19:10:14

标签: haskell

我正在尝试编写函数

fromList :: [e] -> Vector n e
fromList [] = Nil
fromList (x:xs) = x :| fromList xs

使用矢量的这个定义

data Natural where
    Zero :: Natural
    Succ :: Natural -> Natural

data Vector n e where
  Nil  :: Vector Zero e
  (:|) :: e -> Vector n e -> Vector (Succ n) e

infixr :|

然而,Haskell正在给出错误

    Couldn't match type 'Zero with 'Succ n0
    Expected type: Vector n e
      Actual type: Vector ('Succ n0) e
    In the expression: x :| fromList xs
    In an equation for `fromList': fromList (x : xs) = x :| fromList xs
Failed, modules loaded: none.

我认为由于(:|)的类型签名而引发错误。

有没有办法解决这个错误?

1 个答案:

答案 0 :(得分:5)

错误是您的类型签名在n普遍量化,即它表示“对于任何n,我们可以构建一个长度为{{1}的向量”从列表中“。与此不同,函数定义指出向量始终具有给定列表的长度。

基本上,你需要存在量化来定义这个函数(“根据列表长度,会有一个nn是结果的长度向量”)。仅在昨天讨论you can't have existentially-quantified type variables in a signature。你可以拥有的是存在类型 - 最好再写为GADT,

n

然后你可以定义

data DynVector e where
  DynVector :: Vector n e -> DynVector e