Typecheck奇怪与列表列表

时间:2012-05-06 18:23:27

标签: haskell types

我不是Haskell专业人士。今天我对今天的类型系统有一些奇怪的经历。第二行会导致类型错误。问题是第二行的maxdiag (as:bs:cs:ds)位:

maxdiag ((a:as):(b:bs):(c:cs):(d:ds):xs) len =
  maximum [a*(bs !! 0)*(cs !! 1)*(ds !! 2), maxdiag (as:bs:cs:ds) (len-1)]

失败并出现以下错误:

Occurs check: cannot construct the infinite type: a0 = [a0]
Expected type: [[a0]]
  Actual type: [a0]
In the second argument of `(:)', namely `ds'
In the second argument of `(:)', namely `cs : ds'

当我将第二行的违规部分更改为maxdiag (as:bs:cs:ds:xs)时,将其读取

maxdiag ((a:as):(b:bs):(c:cs):(d:ds):xs) len =
  maximum [a*(bs !! 0)*(cs !! 1)*(ds !! 2), maxdiag (as:bs:cs:ds:xs) (len-1)]

...然后没有错误。同样,如果我用maxdiag (as:bs:cs:(ds:xs))替换它就会成功。我的问题是

  1. 这个错误是什么意思?
  2. 为什么会这样?
  3. 为什么这两个看似不同的东西能解决它?

2 个答案:

答案 0 :(得分:9)

要记住的是(:)的类型为a -> [a] -> [a],因此它的第一个参数是一个元素,而第二个参数是一个包含该元素类型的列表。如果元素本身是列​​表,则变为[a] -> [[a]] -> [[a]]

在您的示例中,asbscsds都有[a]类型,而xs类型为{{1}所以[[a]]是一个错误,而cs:ds是良好类型的。

该特定错误消息的原因是,当您尝试在同一类型ds:xs的两件事情上使用(:)时,唯一可行的方法是bb[b]类型相同,但这是一种不允许的无限类型。

对于另一个问题,(:)运算符是右关联的,因此as:bs:cs:ds:xsas:(bs:(cs:(ds:xs)))as:bs:cs:(ds:xs)相同。

答案 1 :(得分:5)

错误:

A.hs:2:63:
    Occurs check: cannot construct the infinite type: a0 = [a0]
    Expected type: [[a0]]
      Actual type: [a0]
    In the second argument of `(:)', namely `ds'
    In the second argument of `(:)', namely `cs : ds'

表示您对类型有递归约束,这是非法的。即您的类型a必须同时为a[a]

occurs check”是此时正在执行的the type checking algorithm部分的技术名称。 “发生检查”可以防止构造无限递归类型。

根据我的经验,如果发生错误,请查看类似列表的错误,这意味着您正在混淆(:)(++)。也就是说,您有时会将值用作列表元素,有时也会将其用作列表本身。

在这种情况下,表达式(:)中使用as:bs:cs:ds。 可能你的意思是:

[as,bs,cs,ds]++xs

请注意,您的代码非常复杂 - 它对列表中元素的数量和形状进行了大量假设,这些假设在任何时候都不太可能是真实的。我会非常害怕这段代码。它会更安全:

  • 使用模式匹配来排除其他情况(例如空列表,缺少元素)
  • 用模式匹配替换索引(!!)。

并仔细思考如何简化算法。