我是Haskell的新手,面临着一个我无法理解的"无法构造无限类型"错误。
事实上,除此之外,我还没有找到一个很好的解释这个错误的含义,所以如果你能超越我的基本问题,解释"无限类型"错误,我真的很感激。
下面是代码:
intersperse :: a -> [[a]] -> [a]
-- intersperse '*' ["foo","bar","baz","quux"]
-- should produce the following:
-- "foo*bar*baz*quux"
-- intersperse -99 [ [1,2,3],[4,5,6],[7,8,9]]
-- should produce the following:
-- [1,2,3,-99,4,5,6,-99,7,8,9]
intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:y:xs) = x:s:y:intersperse s xs
下面是尝试将其加载到解释器中时出现的错误:
Prelude> :load ./chapter.3.ending.real.world.haskell.exercises.hs
[1 of 1] Compiling Main (chapter.3.ending.real.world.haskell.exercises.hs, interpreted )
chapter.3.ending.real.world.haskell.exercises.hs:147:0:
Occurs check: cannot construct the infinite type: a = [a]
When generalising the type(s) for `intersperse'
Failed, modules loaded: none.
在阅读了几个答案并进一步研究后更新(仅供参考,这是在最近的编辑中被某人意外删除的):
以下是一些更正的代码以及处理Haskell中"infinite type"错误的一般准则:
更正代码
intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:xs) = x ++ s:intersperse s xs
问题是什么:
我的类型签名声明第二个要插入的参数是列表的列表,因此,当我对"s(x:y:xs)"进行模式匹配时,x和y变成了列表,但我把x和y当作元素,而不是列表。
处理"无限类型"错误的准则:
大多数情况下,当你遇到这个错误时,你已经忘记了你正在处理的各种变量的类型,并且你试图使用一个变量,就好像它是其他类型的一样。仔细看看每件事是什么类型的,以及你是如何使用它的,这通常会发现问题。
4条答案
按热度按时间but5z9lq1#
问题出在最后一个子句中,你把x和y当作元素,而它们是列表。
发生无限类型错误的原因是:一个运算符的类型是a -〉[a] -〉[a],而你把它当作[a] -〉a -〉[a],这意味着[a]必须与a标识,这意味着a是一个无限嵌套的列表,这是不允许的(而且也不是你想要的)。
**编辑:**上面的代码还有一个bug,应该是:
qfe3c7zg2#
通常,添加显式类型定义可以使编译器的类型错误信息更有意义,但在这种情况下,显式类型定义会使编译器的错误信息更糟糕。
看看当我让ghc猜测插入类型时会发生什么:
这清楚地指出了代码中的bug,使用这种技术,你不必像其他人建议的那样盯着所有的东西,仔细考虑类型。
omhiaaxx3#
也许我错了,但看起来你在试图解决一个更困难的问题,你的
intersperse
版本不仅将值分散在数组中,而且还将其扁平化了一层。Haskell中的
List
模块实际上提供了一个sperse函数,它把给定的值放在列表中的 every 元素之间,例如:我猜这就是你想做的,因为这是我学 haskell 时,我的教授想让我们做的,当然,我可以完全不去.
uhry853o4#
我还找到了this,它解释了错误的含义。
每次解释器/编译器给我这个错误,都是因为我使用了一些类型参数化的元组作为形参,通过删除函数的类型定义,所有的工作都是正确的,它包含类型变量。
我仍然想不出如何既修复它又保留函数类型定义。