为什么这个Haskell代码产生“无限类型”错误?

时间:2021-10-27 17:01:03

I am new to Haskell and facing a "cannot construct infinite type" error that I cannot make sense of.

我是Haskell的新手,面对一个“无法构造无限类型”的错误,我无法理解。

In fact, beyond that, I have not been able to find a good explanation of what this error even means, so if you could go beyond my basic question and explain the "infinite type" error, I'd really appreciate it.

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

Here's the code:

这是代码:

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

And here's the error trying to load it into the interpreter:

这是尝试将其加载到解释器中的错误:

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.

Thanks.

--

Here is some corrected the code and a general guideline for dealing with the "infinite type" error in Haskell:

这里有一些更正了代码和处理Haskell中“无限类型”错误的一般准则:

Corrected code

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

What the problem was:

问题是什么:

My type signature states that the second parameter to intersperse is a list of lists. Therefore, when I pattern matched against "s (x:y:xs)", x and y became lists. And yet I was treating x and y as elements, not lists.

我的类型签名表明散布的第二个参数是列表。因此,当我模式匹配“s(x:y:xs)”时,x和y成为列表。然而,我将x和y视为元素,而不是列表。

Guideline for dealing with the "infinite type" error:

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

Most of the time, when you get this error, you have forgotten the types of the various variables you're dealing with, and you have attempted to use a variable as if it were some other type than what it is. Look carefully at what type everything is versus how you're using it, and this will usually uncover the problem.

大多数情况下,当你收到这个错误时,你已经忘记了你正在处理的各种变量的类型,并且你试图使用一个变量,好像它是一些其他类型的变量。仔细查看所有类型与您使用它的方式类型,这通常可以发现问题。

4 个解决方案

#1


The problem is in the last clause, where you treat x and y as elements, while they are lists. This will work:

问题出在最后一个子句中,您将x和y视为元素,而它们是列表。这将有效:

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

The infinite type error occurs because the : operator has type a -> [a] -> [a], while you treat it as [a] -> a -> [a], which means that [a] must be identified with a, which would mean that a is an infinitely nested list. That is not allowed (and not what you mean, anyway).

发生无限类型错误,因为:运算符具有类型a - > [a] - > [a],而您将其视为[a] - > a - > [a],这意味着必须使用[a]标识a,这意味着a是一个无限嵌套的列表。这是不允许的(反正不是你的意思)。

Edit: there is also another bug in the above code. It should be:

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

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

#2


Often adding an explicit type definition can make the compiler's type error message make more sense. But in this case, the explicit typing makes the compiler's error message worse.

通常添加显式类型定义可以使编译器的类型错误消息更有意义。但在这种情况下,显式类型会使编译器的错误消息更糟。

Look what happens when I let ghc guess the type of intersperse:

看看当我让ghc猜出散布的类型时会发生什么:

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'

That clearly points toward the bug in the code. Using this technique you don't have to stare at everything and think hard about the types, as others have suggested doing.

这清楚地指向代码中的错误。使用这种技术,您不必像其他人所建议的那样盯着所有事物并仔细思考类型。

#3


I may be wrong, but it seems you're trying to solve a more difficult problem. Your version of intersperse doesn't just intersperse the value with the array, but also flattens it one level.

我可能错了,但似乎你正试图解决一个更难的问题。你的穿插版本不只是将值与数组散布在一起,而且还将它展平一层。

The List module in Haskell actually provides an intersperse function. It puts in the value given between every element in the list. For example:

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

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"]

I'm assuming this is what you want to do because it's what my professor wanted us to do when I was learning Haskell. I could, of course, be totally out.

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

#4


Also I found this which explains the meaning of the error.

我也发现这解释了错误的含义。

Every time the interpreter/compiler gives me this error it's because I'm using some type-parametrized tuple as formal parameter. Everything works correctly by removing the type definition of the function, which was containing type variables.

每次解释器/编译器都给我这个错误时,因为我使用了一些类型参数化的元组作为形式参数。通过删除包含类型变量的函数的类型定义,一切正常。

I still cannot figure out how to both fix it and keep the function type definition.

我仍然无法弄清楚如何修复它并保持函数类型定义。

#1


The problem is in the last clause, where you treat x and y as elements, while they are lists. This will work:

问题出在最后一个子句中,您将x和y视为元素,而它们是列表。这将有效:

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

The infinite type error occurs because the : operator has type a -> [a] -> [a], while you treat it as [a] -> a -> [a], which means that [a] must be identified with a, which would mean that a is an infinitely nested list. That is not allowed (and not what you mean, anyway).

发生无限类型错误,因为:运算符具有类型a - > [a] - > [a],而您将其视为[a] - > a - > [a],这意味着必须使用[a]标识a,这意味着a是一个无限嵌套的列表。这是不允许的(反正不是你的意思)。

Edit: there is also another bug in the above code. It should be:

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

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

#2


Often adding an explicit type definition can make the compiler's type error message make more sense. But in this case, the explicit typing makes the compiler's error message worse.

通常添加显式类型定义可以使编译器的类型错误消息更有意义。但在这种情况下,显式类型会使编译器的错误消息更糟。

Look what happens when I let ghc guess the type of intersperse:

看看当我让ghc猜出散布的类型时会发生什么:

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'

That clearly points toward the bug in the code. Using this technique you don't have to stare at everything and think hard about the types, as others have suggested doing.

这清楚地指向代码中的错误。使用这种技术,您不必像其他人所建议的那样盯着所有事物并仔细思考类型。

#3


I may be wrong, but it seems you're trying to solve a more difficult problem. Your version of intersperse doesn't just intersperse the value with the array, but also flattens it one level.

我可能错了,但似乎你正试图解决一个更难的问题。你的穿插版本不只是将值与数组散布在一起,而且还将它展平一层。

The List module in Haskell actually provides an intersperse function. It puts in the value given between every element in the list. For example:

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

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"]

I'm assuming this is what you want to do because it's what my professor wanted us to do when I was learning Haskell. I could, of course, be totally out.

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

#4


Also I found this which explains the meaning of the error.

我也发现这解释了错误的含义。

Every time the interpreter/compiler gives me this error it's because I'm using some type-parametrized tuple as formal parameter. Everything works correctly by removing the type definition of the function, which was containing type variables.

每次解释器/编译器都给我这个错误时,因为我使用了一些类型参数化的元组作为形式参数。通过删除包含类型变量的函数的类型定义,一切正常。

I still cannot figure out how to both fix it and keep the function type definition.

我仍然无法弄清楚如何修复它并保持函数类型定义。