我有查找素数的函数,然后我想写一个函数,它接受一个数字并返回第一个更大的素数。这是我的方法:
isPrime :: (Integral a) => a -> Bool
isPrime x = and $ foldl (\acc y -> (x `mod` y /= 0):acc) [] [2..round . sqrt . fromIntegral $ (x-1)]
primes = filter isPrime [2..]
getNextPrime :: (Integral a) => a -> a
getNextPrime n = head (dropWhile (<n) primes)
但是当我尝试将其导入GHCI时,我收到此错误:
[1 of 1] Compiling Main ( a.hs, interpreted )
a.hs:35:39:
Couldn't match type ‘a’ with ‘Integer’
‘a’ is a rigid type variable bound by
the type signature for getNextPrime :: Integral a => a -> a
at a.hs:34:17
Expected type: [a]
Actual type: [Integer]
Relevant bindings include
n :: a (bound at a.hs:35:14)
getNextPrime :: a -> a (bound at a.hs:35:1)
In the second argument of ‘dropWhile’, namely ‘primes’
In the first argument of ‘head’, namely ‘(dropWhile (< n) primes)’
Failed, modules loaded: none.
但是当我尝试插入时:
head (dropWhile (<30) primes)
它按预期返回31,其类型为Integral
。
我尝试编辑功能类型或明确说明例如n :: Integer
但它没有帮助。我相信这将是一些微不足道的事。
由于
答案 0 :(得分:0)
正如西蒙指出的那样,你需要primes
上的类型签名。以下代码
primes :: (Integral a) => [a]
primes = filter isPrime [2..]
编译。 GHC尝试将没有显式多态签名(即(Integral a) => ...
)的类型转换为具有单形类型的签名。在您的情况下,GHC决定将[2..]
“单形化”为[Integer]
。这被称为“dreaded monomorphism restriction”,其中有许多混淆的SO人员发帖。因此,编译代码的另一种方法是添加语言编译指示-XNoMonomorphismRestriction
,尽管我强烈建议不要将其用于学习Haskell的人。添加类型签名是这里的方法。