Haskell中的“无法创建无限类型”错误

时间:2010-12-14 08:42:36

标签: haskell functional-programming

我想知道为什么Haskell会接受这个

perms xs = [ x:y | i <- [0..(length xs - 1)], x <- [xs!!i], y <- perms (takeOut i xs)]

但不接受:

perms xs = [ x:(perms y) | i <- [0..(length xs - 1)], x <- [xs!!i], y <- (takeOut i xs)]

它抱怨

[1/1]编译Main(abc.hs,解释)

Occurs check: cannot construct the infinite type: t = [t]
  Expected type: t -> [t]
  Inferred type: [t] -> [[a]]
In the second argument of `(:)', namely `(perms y)'
In the expression: x : (perms y)

我能理解它的内容,我不能理解为什么第一个是好的而第二个不是!

编辑:啊,当然我也有

perms [] = [[]]

在顶部。

由于

3 个答案:

答案 0 :(得分:8)

在第一个表达式中,您有x:y,这意味着,如果x :: a则为y :: [a]。 在x : perms y if x :: a中,它必须是perms y :: [a],而是perms y :: [[a]](排列列表)。 Typechecker尝试统一[a][[a]]并失败。

答案 1 :(得分:4)

我的大脑疼,我不是专家,但我想:

perms xs = [ x:y | i <- [0..(length xs - 1)], x <- [xs!!i], y <- perms (takeOut i xs)]

perms(takeOut i xs)是一个列表列表。 x被分配到该列表的每个元素上。 Perms作为一个整体在列表中被调用,因此perms是一个以列表为单位的函数。

perms xs = [ x:(perms y) | i <- [0..(length xs - 1)], x <- [xs!!i], y <- (takeOut i xs)]

(takeOut i xs)是一个列表,对于该列表的每个元素,x被分配到该元素的perms上。在列表的每个元素上调用Perms,因此perms是一个函数。

只有前一种情况在内部是一致的,并且typechecker爱你。

答案 2 :(得分:3)

在列表理解中,x <- ysx绑定到ys中的每个元素。从本质上讲,你正试图改变:

[ f foo | foo <- bar ]

[ f bar ]

短语

y <- perms (takeOut i xs)

表示“y的每个排列takeOut i xs”。因此[ x:y | ... ]会为每个排列添加x

相应地,短语

y <- takeOut i xs

表示“y”的每个元素takeOut i xs。因此,[ x:perms y | ... ]正在尝试查找元素 y的所有排列(甚至不是列表),然后将x添加到该排列列表中。某些内容的排列是一个列表列表,因此x必须是一个列表来执行此操作,而不是。所以,基本上,第二个没有意义。

我明白为什么你会被抛弃。请记住,<-let不同,对每个都意味着