我正在尝试使用 Haskell 解决 Project Euler 上的第二个问题。问题相当简单 - 将偶数斐波那契数相加小于 4000000。(我是强制症患者,我正在实现一个稍微修改过的函数 - 一个允许任意限制的函数)。
我最初的代码是:
euler2 limit (num1:num2)
|(num1>limit) = 0
|((num2>limit) && ((mod num1 2) == 0)) = num1
|(num2>limit) = 0
|(((mod num1 2) == 0) && ((mod num2 2) == 0)) = num1+num2+(euler2 limit [num1+num2,num1+num2+num2])
|((mod num1 2) == 0) = num1+(euler2 limit [num1+num2,num1+num2+num2])
|((mod num2 2) == 0) = num2+(euler2 limit [num1+num2,num1+num2+num2])
|otherwise = euler2 limit [num1+num2,num1+num2+num2]
euler2 limit [] = euler2 limit [1,2]
这产生了以下错误:
Occurs check: cannot construct the infinite type: a0 = [a0]
In the second argument of `(>)', namely `limit'
In the first argument of `(&&)', namely `(num2 > limit)'
In the expression: ((num2 > limit) && ((mod num1 2) == 0))
现在通过一些试验和错误,我意识到它正在尝试将 num2
类型转换为列表,并且这个小变化:
euler2 limit (num1:num2:[]) | (num1 > limit) = 0
解决了问题。我的问题是为什么?发生了什么以及为什么它拒绝将 num1
和 num2
转换为 Int?
最佳答案
(:)
的类型是
(:) :: a -> [a] -> [a]
如果您有模式匹配
euler2 limit (num1:num2)
名称 num1
和 num2
绑定(bind)到构造函数 (:)
的相应参数(如果提供的参数是非空列表) ),因此 num2
是一个列表,其元素的类型为 num1
。
如果你匹配
(num1:num2:[])
隐含括号
(num1 : (num2 : []))
现在 num2 : []
与顶级 (:)
的第二个参数列表相匹配,并且匹配成功,绑定(bind) num2
到第二个列表元素,如果提供的参数是恰好包含两个元素的列表。
关于Haskell 无法构造无限类型 : a0 = [a0],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14780214/