我试过了:
composites=[c|c<-[4..], any (\p->(c`mod`p == 0)) (takeWhile (< (sqrt c)) primes)]
primes=2:[p|p<-[3..], not p `elem` (takeWhile (<p) composites)]
并得到:
pad.hs:1:19:
No instance for (Num Bool) arising from the literal `4'
Possible fix: add an instance declaration for (Num Bool)
In the expression: 4
In the expression: [4 .. ]
In a stmt of a list comprehension: c <- [4 .. ]
pad.hs:1:30:
No instance for (Integral Bool) arising from a use of `divisible'
Possible fix: add an instance declaration for (Integral Bool)
In the first argument of `any', namely `(divisible c)'
In the expression: any (divisible c) (factors c)
In a stmt of a list comprehension: any (divisible c) (factors c)
pad.hs:3:43:
No instance for (Floating Bool) arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Bool)
In the second argument of `(<)', namely `sqrt c'
In the first argument of `takeWhile', namely `(< sqrt c)'
In the expression: takeWhile (< sqrt c) primes
Failed, modules loaded: none.
我认为它处理的是什么类型的数字感到困惑,但我不确定。有小费吗?
最佳答案
I think that it is confused as to what type of number it is dealing with
非常正确!那你为什么不告诉呢?在实际实现之前,最好在Haskell中编写函数签名。这不仅可以防止发生错误时引起混淆的编译器消息,而且还为实际设计函数提供了非常好的指南。
因此,就您而言,您可能想要1
composites, primes :: [Integer]
哪个当然不能解决问题,但可以使错误消息更加清晰:
Prelude> let composites,primes::[Integer]; composites=[c|c<-[4..], any (\p -> c`mod`p == 0) (takeWhile (< sqrt c) primes)]; primes=2:[p|p<-[3..], not p `elem` (takeWhile (< p) composites)]
<interactive>:2:128:
Couldn't match expected type `Integer' with actual type `Bool'
In the expression: p
In the second argument of `(:)', namely
`[p | p <- [3 .. ], not p `elem` (takeWhile (< p) composites)]'
In the expression:
2 : [p | p <- [3 .. ], not p `elem` (takeWhile (< p) composites)]
<interactive>:2:169:
Couldn't match type `Integer' with `Bool'
Expected type: [Bool]
Actual type: [Integer]
In the second argument of `takeWhile', namely `composites'
In the second argument of `elem', namely
`(takeWhile (< p) composites)'
In the expression: not p `elem` (takeWhile (< p) composites)
仍然不是很准确,但是至少现在可以将错误定位到它的位置:在
primes
中,p
推断为Bool
,这当然是错误的。出现bool的原因是您在那里有not p `elem` (...)
。显然您认为这被解析为not (p`elem`(...))
,但事实并非如此:普通前缀函数应用程序的优先级高于任何infix运算符。要知道的一件事很重要(这也是为什么您不需要在sqrt c
中的(< sqrt c)
周围加括号的原因)。解决这个问题,然后还有一个问题:
Prelude> let composites,primes::[Integer]; composites=[c|c<-[4..], any (\p->(c`mod`p == 0)) (takeWhile (< (sqrt c)) primes)]; primes=2:[p|p<-[3..], not $ p `elem` (takeWhile (<p) composites)]
<interactive>:3:99:
No instance for (Floating Integer) arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Integer)
In the second argument of `(<)', namely `(sqrt c)'
In the first argument of `takeWhile', namely `(< (sqrt c))'
In the second argument of `any', namely
`(takeWhile (< (sqrt c)) primes)'
现在就可以了:您正在处理整数,但是
sqrt
显然会产生通常不合理的数字,因此只有Floating
类型才有意义。为了解决这个问题,您可以使用sqrt' = round . sqrt . fromIntegral
(非常难看,但是可以)。1实际上,这种单态签名可能并不理想-出于各种原因(主要是效率),您可能更喜欢
Int
。为了安全起见,请选择Integral a => [a]
;但是,多态值不会在顶层“存储”,这在此示例中再次成为问题。
关于haskell - Haskell素数生成器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19737866/