そこで、Haskell をいじってみることにしました。Project Euler の最初の問題を解決しようとしています。以下は私のコードです:
euler1 limit (div:divisors) = if limit > 1 then (euler1 limit divisors) + (euler1 limit (div:[])) + (euler1 (limit-1) (div:divisors)) else 0
euler1 limit (divisor:[]) = if limit > 1 && (mod limit divisor) == 0 then limit else 0
euler1 limit [] = 0
ただし、これを ghci で実行すると、次のようになります。
euler1 9 [3,5]
*** Exception: <interactive>:3:5-90: Non-exhaustive patterns in function euler1
さらなるデバッグ:
euler1 5 []
0
euler1 5 [5]
*** Exception: <interactive>:3:5-90: Non-exhaustive patterns in function euler1
これは、壊れたコードが euler1 に再帰ステップさえ含まれていない 2 番目のケース (要素が 1 つのリスト) にあることを示唆しています。
どうしたの?なぜこれほどまでに見事に割れているのでしょうか。私が見逃したパターンは何ですか?(単一要素リスト、複数要素リスト、空のリストはありませんか?)
編集:私が最初に上で提供した解決策を気にする人にとっては(John Lsの素晴らしい助けを借りて)、1つ以上の約数の倍数であるアイテムを2回以上カウントするため、まだ正しくありません。最終的な、正しく動作するアルゴリズムは次のとおりです。
euler1 limit (divisor:[]) = if ((limit > 1) && ((mod limit divisor) == 0)) then limit else 0
euler1 limit (div:divisors) | ((limit > 1) && (euler1 limit (div:[]))==0) = (euler1 limit divisors) + (euler1 (limit-1) (div:divisors)) | ((limit > 1) && (euler1 limit (div:[]))/=0) = (euler1 limit (div:[])) + (euler1 (limit-1) (div:divisors)) |limit > 1 = euler1 (limit-1) (div:divisors) | otherwise = 0
euler1 limit [] = 0