为什么foldr会给我这个错误?

时间:2017-12-01 11:40:08

标签: haskell

foldr (\x ante->[x]:[ante]) [4] [1,2,3]

因此,如果我得到正确的折叠,第一次函数(\x ante->[x]:[ante])将执行某些操作,我将调用此函数f,它将在:

   f 3 [4] = [3]:[[4]] = [[3],[4]]

为什么这个功能没有这样做?它显示此错误:

* Occurs check: cannot construct the infinite type: a ~ [a]
  Expected type: [a]
    Actual type: [[a]]
* In the expression: [x] : [ante]
  In the first argument of `foldr', namely
    `(\ x ante -> [x] : [ante])'
  In the expression: foldr (\ x ante -> [x] : [ante]) [4] [1, 2, 3]
* Relevant bindings include
    ante :: [a] (bound at testefoldr.hs:51:21)
    x :: a (bound at testefoldr.hs:51:19)
    folder4 :: [a] (bound at testefoldr.hs:51:1)
   |51 | folder4 = foldr (\x ante->[x]:[ante]) [4] [1,2,3]    

我创建了一个.hs然后我放了

folder4 = foldr (\x ante->[x]:[ante]) [4] [1,2,3]

更快的测试。这就是错误中存在folder4的原因。

2 个答案:

答案 0 :(得分:4)

foldr函数的类型为:

foldr :: (a -> b -> b) -> b -> [a] -> b

这意味着它将列表的元素(类型a)作为输入与累加器(类型b)一起折叠,并返回一个累加器(再次输入{{1 }})。如果Haskell没有静态类型,它每次都会将累加器包装在一个新列表中。所以它会导致:

b

没有任何意义。

这里有两个问题:

  1. 如果[4] -> [[3],[4]] -> [[2],[[3],[4]]] -> [[1],[[2],[[3],[4]]]] 的类型为ante,则b的类型为[x] : [ante];和
  2. 初始累加器[b]的类型不是折叠器的结果。
  3. 所以你可以通过写:

    来解决这个问题
    [4]

答案 1 :(得分:3)

让我们假装这种类型检查,并运行它

foldr (\x ante->[x]:[ante]) [4] [1,2,3]

让我们为f撰写\x ante -> [x]:[ante]

foldr f [4] [1,2,3]
=
f 1 (f 2 (f 3 [4]))
=
f 1 (f 2 ([3]:[[4]]))
=
f 1 (f 2 [[3],[4]])

到目前为止,非常好。

=
f 1 ([2] : [[[3],[4]]])
=
f 1 [[2] , [[3],[4]] ]

现在我们遇到了麻烦。那是[[Int]]还是[[[Int]]]? 如果我们继续下去,事情会变得更糟。

问题是f必须返回与第二个参数类型相同的值。否则,我们无法以f的方式撰写foldr。您的f不会这样做,而是在每次通话时为该类型添加[]