简体   繁体   English

Haskell错误; 进行检查:无法构造无限类型:t〜[t]

[英]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)并且yssub (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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM