1)問題はsqrt
、タイプ(Floating a) => a -> a
が であるが、整数を引数として使用しようとすることです。したがって、最初に Integer を Floating に変換する必要があります。たとえば、次のように記述します。sqrt (fromIntegral x)
2) == が遅延してはならない理由はわかりませんが、空のコレクションをテストするには、null
関数を使用できます (無限リストで機能するため、これは間違いなく遅延です)。
isPrime :: Integer->Bool
isPrime x = null [y | y<-[2..floor (sqrt (fromIntegral x))], x `mod` y == 0]
しかし、より慣用的な解決策を得るには、問題をより小さなサブ問題に分割します。まず、y*y <= x であるすべての要素 y のリストが必要です。
takeWhile (\y -> y*y <= x) [2..]
次に、x を分割する要素のみが必要です。
filter (\y -> x `mod`y == 0) (takeWhile (\y -> y*y <= x) [2..])
次に、そのリストが空かどうかを確認する必要があります。
isPrime x = null (filter (\y -> x `mod`y == 0) (takeWhile (\y -> y*y <= x) [2..]))
そして、これがあなたにぎこちないように見える場合は、括弧の一部を $ に置き換えてください
isPrime x = null $ filter (\y -> x `mod` y == 0) $ takeWhile (\y -> y*y <= x) [2..]
さらに明確にするために、ラムダを「アウトソーシング」できます。
isPrime x = null $ filter divisible $ takeWhile notTooBig [2..] where
divisible y = x `mod`y == 0
notTooBig y = y*y <= x
null $ フィルターを not $ any に置き換えることで、ほとんど「人間が読める」ものにすることができます。
isPrime x = not $ any divisible $ takeWhile notTooBig [2..] where
divisible y = x `mod`y == 0
notTooBig y = y*y <= x