Haskell错误;发生检查:无法构造无限类型:t~ [t]

时间:2015-01-24 12:01:43

标签: haskell ghci

昨天我问了几个问题,我的代码中越来越多的问题不断涌现。

我有一个名为sub的函数。 Sub接收一个数字并输出一个数字列表,代码如下。

sub 5 =  [1]
sub x =
    do 
        xs <- sub (x - 1)
        (x:xs)  

我曾经在顶线的位置有sub 5 = return [1]而在底线,返回(x:xs)。昨天有人回答并告诉我把它们拿出来,因为它把列表放在一个列表中,就像[[int]]一样。如果我拿出退货会产生错误(在问题标题中),我真的无法理解这一点。

只是想知道是否有人能理解它,

谢谢

2 个答案:

答案 0 :(得分:3)

我会尝试扩展错误的含义。

让desugar记谱法(details):

sub 5 =  [1]
sub x =
        sub (x - 1) >>= \xs ->
        (x:xs)  

>>=运算符具有下一种类型(请参阅here):

(>>=) :: Monad m => m a -> (a -> m b) -> m b

它的第一个参数sub (x - 1)的类型为[Int],因此我们可以将类型变量m实例化为[],将a实例化为{{1} }:

Int

(请注意(>>=) :: [Int] -> (Int -> [b]) -> [b] 是列表类型的特殊语法,您可以将其读作[a]

所以第二个参数[] a应该有\xs -> (x:xs)类型。现在应该很清楚Int -> [b]类型xs,而不是Int,正如您所期望的那样。

现在让我们考虑[Int]。它的类型是:。记下所有约束:

c -> [c] -> [c]

他们无法同时满足,因为他们需要(:) :: c -> [c] -> [c] x :: Int xs :: Int x : xs :: [Int] c [c]

答案 1 :(得分:0)

让我们重写一下你必须弄清楚为什么这不会成为一个类型检查。我们首先考虑得到记号

sub :: Int -> [Int]
sub 5 = [1]
sub x = sub (x-1) >>= \xs -> (x:xs)

现在回想一下如何为列表定义>>=ys >>= f = concat (map f ys)。此处f\xs -> (x:xs)yssub (x-1),因此我们有:{/ p>

sub :: Int -> [Int]
sub 5 = [1]
sub x = concat (map (\xs -> (x:xs)) (sub (x-1)))

sub (x-1)的类型为[Int],因此map的第一个参数必须是一个Int的函数。它不是 - 它需要一个清单!

正如您所说,您曾经拥有sub 5 = return [1]。回想一下,对于列表return y = [y],在这种情况下,您的sub会有签名Int -> [[Int]]。现在上面的sub (x-1)将是一个列表列表,map的第一个参数应该是一个带列表的函数,实际情况就是如此。所以事情就变得很糟糕了。

一条建议:为您的顶级定义提供明确的签名(是sub :: Int -> [Int]还是sub :: Int -> [[Int]]?)!它会让您更容易理解正在发生的事情,因为它会迫使您思考您的实际需求。