简体   繁体   English

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

[英]haskell fibonacci - cannot construct the infinite type: a0 = [a0]

I was trying to get an infinite list of fibonacci numbers in haskell but the following code would not compile: 我试图在haskell中获取无限数量的斐波那契数字,但以下代码无法编译:

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

I eventually got it to work with this code: 我最终将其与以下代码一起使用:

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

Still, I do not understand why the first code snippet did not compile. 不过,我仍然不明白为什么第一个代码段没有编译。 The error is below. 错误如下。 I am just looking for an answer as to why the first one doesn't compile but the second does. 我只是在寻找一个答案,为什么第一个不编译而第二个却编译。

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.

The problem with the first code sample is that there is no way you could write a type annotation for it. 第一个代码示例的问题在于,您无法为其编写类型注释。 It would be infinite. 这将是无限的。 Let's try it anyway: 让我们尝试一下:

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

First let's simplify it, because we can replicate the same problem without the last and init stuff: 首先让我们简化一下,因为我们可以复制相同的问题而无需使用lastinit东西:

fib1 x = fib1 (x : undefined)

What is the type of fib1 's argument. fib1的参数类型是什么。 On the left, we only see x with no more information about it. 在左侧,我们仅看到x ,没有更多有关它的信息。 We can assume it has some type a . 我们可以假设它的类型为a On the right hand side, we try to call the function with argument which must be a list (because it is constructed by : operator). 在右侧,我们尝试使用必须为列表的参数调用该函数(因为它是由:运算符构造的)。 Elements of the list start with x , which has type a . 列表的元素以x开头, x类型为a Therefore, the type of fib1 's argument here is [a] . 因此,此处fib1的参数类型为[a] Since we can't call a function with arguments of two different types, even on left side x must have type [a] . 由于我们无法使用两种不同类型的参数来调用函数,因此即使在x左侧也必须具有[a]类型。 But this forces us to update the type on the rigth side to [[a]] . 但是,这迫使我们将严格类型的类型更新为[[a]] And then again on the left. 然后再次在左边。 This process will never stop, the type will grow and grow, because there is no way to unify a with [a] . 这个过程永远不会停止,种类会不断地成长,因为没有办法统一a[a] Therefore there is no valid type for the expression and GHC will reject it. 因此,该表达式没有有效的类型,GHC将拒绝它。

On the other hand, the second snippet does not have the problem. 另一方面,第二个片段没有问题。

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

We can easily ask GHCi the type of this function, and it will happily answer us: 我们可以轻松地询问GHCi此函数的类型,它会很高兴地回答我们:

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

That type is perfectly finite. 该类型是完全有限的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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