为什么Haskell代码会产生“无限types”错误?

我是Haskell的新手,面临着我无法理解的“无法构造无限types”的错误。

事实上,除此之外,我还没有find一个很好的解释这个错误甚至意味着什么,所以如果你能超越我的基本问题,解释“无限types”的错误,我真的很感激。

代码如下:

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中的“无限types”错误的一般指导:

更正的代码

 intersperse _ [] = [] intersperse _ [x] = x intersperse s (x:xs) = x ++ s:intersperse s xs 

问题是:

我的types签名声明第二个参数intersperse是一个列表的列表 。 因此,当我模式匹配“s(x:y:xs)”时,x和y成为列表 。 然而,我把x和y当作元素,而不是列表。

处理“无限types”错误的指南:

大多数情况下,当你得到这个错误时,你已经忘记了你正在处理的各种variables的types,并且你试图使用一个variables,就像它是一个其他types的variables。 仔细看看什么types的东西,以及如何使用它,这通常会发现问题。

问题是在最后一个条款中,您将x和y作为元素,而它们是列表。 这将工作:

 intersperse _ [] = [] intersperse _ [x] = x intersperse s (x:y:xs) = x ++ [s] ++ y ++ intersperse s xs 

发生无限types错误的原因是:操作符的types是a – > [a] – > [a],而您将其视为[a] – > a – > [a],这意味着[a]必须用a,这意味着a是一个无限的嵌套列表。 这是不允许的(而不是你的意思,无论如何)。

编辑:在上面的代码还有另一个错误。 它应该是:

 intersperse _ [] = [] intersperse _ [x] = x intersperse s (x:xs) = x ++ [s] ++ intersperse s xs 

通常添加一个明确的types定义可以使编译器的types错误消息更有意义。 但是在这种情况下,显式types会使编译器的错误信息变得更糟。

看看当我让ghc猜测散布的types时会发生什么:

 Occurs check: cannot construct the infinite type: a = [a] Expected type: [a] -> [[a]] -> [[a]] Inferred type: [a] -> [[a]] -> [a] In the second argument of `(:)', namely `intersperse s xs' In the second argument of `(:)', namely `y : intersperse s xs' 

这清楚地指向代码中的错误。 使用这种技术,您不必像所有人所暗示的那样盯着所有的东西,并且仔细考虑types。

我可能是错的,但似乎你正在试图解决一个更困难的问题。 你的版本intersperse不仅仅是散布数组的值,而且也将它平滑到一个层次。

Haskell中的List模块实际上提供了一个intersperse函数。 它列出了列表中每个元素之间的值。 例如:

 intersperse 11 [1, 3, 5, 7, 9] = [1, 11, 3, 11, 5, 11, 7, 11, 9] intersperse "*" ["foo","bar","baz","quux"] = ["foo", "*", "bar", "*", "baz", "*", "quux"] 

我假设这是你想要做的,因为这是我的教授希望我们在学习Haskell时做的事情。 当然,我完全可以。

我还发现这个解释错误的含义。

每次解释器/编译器给我这个错误,这是因为我使用了一些types参数化的元组作为forms参数。 通过删除包含typesvariables的函数的types定义,一切正常工作。

我仍然不知道如何解决这个问题,并保持函数types定义。