[英]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: 首先让我们简化一下,因为我们可以复制相同的问题而无需使用last
和init
东西:
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.