2

Haskellを使ってプロジェクトオイラーの2番目の問題を解決しようとしています。問題はかなり単純です-4000000未満の偶数フィボナッチ数を合計します(私はOCDであり、わずかに変更された関数を暗示しています-仲裁制限を許可するものです)。

私の最初のコードは次のとおりです。

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として拒否したのですか?

4

1 に答える 1

6

タイプ(:)

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

パターンマッチがある場合

euler2 limit (num1:num2)

名前num1num2はコンストラクターの対応する引数にバインドさ(:)れます(指定された引数が空でないリストの場合)。したがってnum2、要素のタイプが。であるリストですnum1

あなたが一致する場合

(num1:num2:[])

暗黙的に括弧で囲まれています

(num1 : (num2 : []))

そして今num2 : []、トップレベルの2番目の引数であるリストと一致し、指定された引数が正確に2つの要素を持つリストである場合(:)、その一致は成功num2し、2番目のリスト要素にバインドされます。

于 2013-02-08T20:51:36.597 に答える