我不是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))
替换它就会成功。我的问题是
答案 0 :(得分:9)
要记住的是(:)
的类型为a -> [a] -> [a]
,因此它的第一个参数是一个元素,而第二个参数是一个包含该元素类型的列表。如果元素本身是列表,则变为[a] -> [[a]] -> [[a]]
。
在您的示例中,as
,bs
,cs
和ds
都有[a]
类型,而xs
类型为{{1}所以[[a]]
是一个错误,而cs:ds
是良好类型的。
该特定错误消息的原因是,当您尝试在同一类型ds:xs
的两件事情上使用(:)
时,唯一可行的方法是b
是b
与[b]
类型相同,但这是一种不允许的无限类型。
对于另一个问题,(:)
运算符是右关联的,因此as:bs:cs:ds:xs
与as:(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
请注意,您的代码非常复杂 - 它对列表中元素的数量和形状进行了大量假设,这些假设在任何时候都不太可能是真实的。我会非常害怕这段代码。它会更安全:
并仔细思考如何简化算法。