[英]Haskell Error; Occurs check: cannot construct the infinite type: t ~ [t]
I asked a few questions yesterday and more and more problems kept creeping up in my code. 昨天我问了几个问题,越来越多的问题在我的代码中不断蔓延。
I have a function called sub. 我有一个叫做sub的函数。 Sub takes in a number and outputs a list of numbers, the code is below.
Sub接受一个数字并输出数字列表,代码如下。
sub 5 = [1]
sub x =
do
xs <- sub (x - 1)
(x:xs)
I used to have to where on the top line had sub 5 = return [1] and on the bottom line, return (x:xs). 我曾经不得不在最上面一行有sub 5 = return [1]的地方,在最下面一行是return(x:xs)。 Someone answered yesterday and told me to take these out as it's putting a list within a list, like so [[int]].
昨天有人回答,并告诉我将其删除,因为它会将列表放在列表中,例如[[int]]。 If I take out the returns this generates an error (In the question title), I really can't get my head around this.
如果我拿出退货,这会产生一个错误(在问题标题中),我真的无法解决这个问题。
Just wondering if anyone can make sense of it, 只是想知道是否有人可以理解它,
Thanks 谢谢
I'll try to expand what the error means. 我将尝试扩大错误的含义。
Lets desugar do notation ( details ): 让desugar做符号( 详细信息 ):
sub 5 = [1]
sub x =
sub (x - 1) >>= \xs ->
(x:xs)
The >>=
operator has the next type (see here ): >>=
运算符具有下一个类型(请参见此处 ):
(>>=) :: Monad m => m a -> (a -> m b) -> m b
The first its argument, sub (x - 1)
, has type [Int]
, so we can instantiate type variables m
to []
and a
to Int
: 它的第一个参数
sub (x - 1)
类型为[Int]
,因此我们可以将类型变量m
实例化为[]
并将a
实例化为Int
:
(>>=) :: [Int] -> (Int -> [b]) -> [b]
(Note that [a]
is a special syntax for list type, you can read it as [] a
) (请注意,
[a]
是列表类型的特殊语法,您可以将其读为[] a
)
So the second argument, \\xs -> (x:xs)
, should have type Int -> [b]
. 因此,第二个参数
\\xs -> (x:xs)
类型应为Int -> [b]
。 It should be clear now that xs
has type Int
, not [Int]
as you seems to expect. 现在应该清楚
xs
类型为Int
,而不是您期望的[Int]
类型。
Now lets consider :
. 现在考虑
:
。 Its type is c -> [c] -> [c]
. 它的类型是
c -> [c] -> [c]
。 Let write down all constrains: 让我们写下所有约束:
(:) :: c -> [c] -> [c]
x :: Int
xs :: Int
x : xs :: [Int]
They can't be satisfied at the same time because they require c
and [c]
both to be Int
. 他们不能同时满足,因为它们要求
c
和[c]
都必须为Int
。
Let's rewrite what you have to make clearer why this won't typecheck. 让我们重写您必须更清楚地说明为什么不会进行类型检查的内容。 We first desugar the do notation to get
我们首先将“糖”去糖
sub :: Int -> [Int]
sub 5 = [1]
sub x = sub (x-1) >>= \xs -> (x:xs)
Now recall how >>=
is defined for lists: ys >>= f = concat (map f ys)
. 现在回想一下
>>=
是如何为列表定义的: ys >>= f = concat (map f ys)
。 Here f
is \\xs -> (x:xs)
and ys
is sub (x-1)
, so therefore we have: 这里
f
是\\xs -> (x:xs)
并且ys
是sub (x-1)
,因此我们有:
sub :: Int -> [Int]
sub 5 = [1]
sub x = concat (map (\xs -> (x:xs)) (sub (x-1)))
The type of sub (x-1)
is [Int]
, so the first argument to map
must be a function that takes an Int
. sub (x-1)
的类型为[Int]
,因此map
的第一个参数必须是采用Int
的函数。 It is not - it expects a list! 不是-它需要一个清单!
As you say, you used to have sub 5 = return [1]
. 就像您说的那样,您曾经有
sub 5 = return [1]
。 Recall that for lists return y = [y]
, so in that case your sub
would have signature Int -> [[Int]]
. 回想一下,对于列表
return y = [y]
,因此在这种情况下,您的sub
将具有签名Int -> [[Int]]
。 Now sub (x-1)
in the above would be a list of lists, and the first argument to map
should be a function that takes lists , which is indeed the case. 现在,上面的
sub (x-1)
将是列表的列表,而map
的第一个参数应该是一个接受list的函数,的确如此。 So things typechecked. 所以事情经过了检查。
A piece of advice: Give your top-level definitions explicit signatures (is it sub :: Int -> [Int]
or sub :: Int -> [[Int]]
that you want?)! 一条建议:给您的顶级定义显式签名(是您想要的
sub :: Int -> [Int]
还是sub :: Int -> [[Int]]
?)! It'll make it easier to understand what's going on because it forces you to think about what you actually want. 它将使您更容易理解正在发生的事情,因为它会迫使您考虑自己真正想要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.