2

我正在尝试使用 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

解决问题。我的问题是为什么?发生了什么事,为什么它拒绝转换num1num2Ints?

4

1 回答 1

6

的类型(:)

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

如果您有模式匹配

euler2 limit (num1:num2)

名称num1num2绑定到构造函数的相应参数(:)(如果提供的参数是非空列表),因此num2是一个列表,其元素的类型为num1.

如果你匹配

(num1:num2:[])

那是隐式括起来的

(num1 : (num2 : []))

并且 nownum2 : []与作为 top-level 的第二个参数的列表(:)匹配,并且匹配成功,绑定num2到第二个列表元素,如果提供的参数是一个恰好包含两个元素的列表。

于 2013-02-08T20:51:36.597 回答