haskell fibonacci - 无法构造无限类型:a0 = [a0]

时间:2015-04-12 06:52:18

标签: haskell

我试图在haskell中获得无限的斐波纳契数列表,但以下代码无法编译:

fib1 x = fib1 (x : (last $ init x) + (last x))
result1 = fib1 [1,2]

我最终使用了这段代码:

fib2 x y = head y : fib2 y (zipWith (+) x y)
result2 = fib2 [0,1] [1,1]

但是,我不明白为什么第一个代码片段没有编译。错误如下。我只是在寻找一个答案,为什么第一个没有编译,但第二个没有。

p2.hs:3:16:
    Occurs check: cannot construct the infinite type: a0 = [a0]
    In the first argument of `(:)', namely `x'
    In the first argument of `fib1', namely
      `(x : (last $ init x) + (last x))'
    In the expression: fib1 (x : (last $ init x) + (last x))

p2.hs:3:21:
    Occurs check: cannot construct the infinite type: a0 = [a0]
    In the first argument of `(+)', namely `(last $ init x)'
    In the second argument of `(:)', namely
      `(last $ init x) + (last x)'
    In the first argument of `fib1', namely
      `(x : (last $ init x) + (last x))'

p2.hs:3:44:
    Occurs check: cannot construct the infinite type: a0 = [a0]
    Expected type: [[a0]]
      Actual type: [a0]
    In the first argument of `last', namely `x'
    In the second argument of `(+)', namely `(last x)'
    In the second argument of `(:)', namely
      `(last $ init x) + (last x)' Failed, modules loaded: none.

1 个答案:

答案 0 :(得分:4)

第一个代码示例的问题是您无法为其编写类型注释。这将是无限的。让我们试试吧:

fib1 x = fib1 (x : (last $ init x) + (last x))

首先让我们对其进行简化,因为我们可以在没有lastinit内容的情况下复制相同的问题:

fib1 x = fib1 (x : undefined)

fib1的论点是什么类型。在左侧,我们只看到x,但没有关于它的更多信息。我们可以假设它有一些类型a。在右侧,我们尝试使用参数调用函数,该参数必须是列表(因为它由:运算符构造)。列表元素以x开头,其类型为a。因此,此处fib1的参数类型为[a]。由于我们无法使用两种不同类型的参数调用函数,因此即使在左侧x,也必须具有类型[a]。但这迫使我们将严谨方面的类型更新为[[a]]。然后再在左边。此过程永远不会停止,类型会增长和增长,因为无法将a[a]统一起来。因此表达式没有有效类型,GHC会拒绝它。

另一方面,第二个片段没有问题。

fib2 x y = head y : fib2 y (zipWith (+) x y)

我们可以轻松地向GHCi询问此功能的类型,并乐意回答我们:

Prelude> let fib2 x y = head y : fib2 y (zipWith (+) x y) Prelude> :t fib2 fib2 :: Num a => [a] -> [a] -> [a]

这种类型是完全有限的。