我试过了:
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.
我认为它处理的是什么类型的数字很困惑,但我不确定。有什么提示吗?
答案 0 :(得分:2)
我认为它与处理的数字类型相混淆
非常正确!那么你为什么不告诉它呢?在实际实现之前,在Haskell中编写函数签名总是一个好主意。当出现问题时,这不仅可以防止这些令人困惑的编译器消息,而且在实际设计函数时它也是一个非常好的指南。
所以在你的情况下,你可能想要 1
composites, primes :: [Integer]
当然不能解决问题,但它会使错误信息更加清晰:
前奏&GT;让复合材料,素数:: [整数]; composites = [c | c&lt; - [4 ..],any(\ p - &gt; c`mod`p == 0)(takeWhile(&lt; sqrt c)primes)]; primes = 2:[p | p&lt; - [3 ..],而不是p`elem`(takeWhile(&lt; p)composites)]
&LT;互动&GT;:2:128:
无法将预期类型“Integer”与实际类型“Bool”匹配 在表达式中:p
在`(:)'的第二个参数中,即
`[p | p&lt; - [3 ..],而不是p`elem`(takeWhile(&lt; p)复合材料)]'
在表达式中:
2:[p | p&lt; - [3 ..],而不是p`elem`(takeWhile(&lt; p)复合材料)]
&LT;互动&GT;:2:169:
无法将类型“Integer”与“Bool”匹配 预期类型:[Bool]
实际类型:[整数]
在“takeWhile”的第二个论点中,即`composites' 在“elem”的第二个参数中,即
`(takeWhile(&lt; p)复合材料)'
在表达式中:not p`elem`(takeWhile(&lt; p)composites)
它仍然不完全正确,但至少它现在将错误本地化到它的位置:在primes
中,p
被推断为Bool
,这当然是错误。 bool的原因是你有not p `elem` (...)
。显然你认为这被解析为not (p`elem`(...))
,但事实并非如此:普通前缀函数应用程序具有比任何中缀运算符更高的优先级。重要的是要知道(这也是为什么你不需要sqrt c
中(< sqrt c)
周围的parens。
让我们解决这个问题,然后还有一个问题:
前奏&GT;让复合材料,素数:: [整数]; composites = [c | c&lt; - [4 ..],any(\ p-&gt;(c`mod`p == 0))(takeWhile(&lt;(sqrt c))primes)]; primes = 2:[p | p&lt; - [3 ..],而不是$ p`elem`(takeWhile(&lt; p)composites)]
&LT;互动&GT;:3:99:
没有因使用“sqrt”而产生的(浮动整数)实例 可能的解决方法:为(Floating Integer)添加实例声明
在`(&lt;)'的第二个参数中,即`(sqrt c)' 在`takeWhile'的第一个参数中,即`(&lt;(sqrt c))' 在“任何”的第二个论点中,即
`(takeWhile(&lt;(sqrt c))primes)'
现在已经发现:你正在处理整数,但是sqrt
显然会产生一般无理数,所以只有Floating
类型才有意义。为了解决这个问题,你可以使用(诚然丑陋,但确定)sqrt' = round . sqrt . fromIntegral
。
1 实际上,这种单态签名可能并不理想 - 出于各种原因(主要是效率),您可能更喜欢Int
。为了安全起见,可以选择Integral a => [a]
;但是多态值不会在顶层“记忆”,这在这个例子中也是一个很大的问题。
答案 1 :(得分:1)
任何提示?
好了,现在你修好了,
composites=[c|c<-[4..], any ((==0).(c`mod`)) (takeWhile ((<= c).(^2)) primes)]
primes=2:[p|p<-[3..], not (p `elem` takeWhile (<= p) composites)]
考虑是否可以加快速度。首先,elem
完全消耗第二个参数,当第一个参数不在其中时,始终从头开始搜索。但是,如果我们只是在合成中搜索 16 ,那么当我们搜索 17 时,就没有必要重新开始了 strong> next - 我们可以从同一点继续:
notAmong (_, (k:ks,c:cs)) -- a candidate that is not among
| k == c = (Nothing, (ks,cs)) -- the composites, is a prime
| otherwise = (Just k, (ks,c:cs)) -- (k < c)
primes = 2 : [p | (Just p,_) <- iterate notAmong (Just 3, ([4..],composites))]
我们融合函数not
,elem
和takewhile
,速度很快。
尝试找出此版本的empirical orders of growth并与原始版本进行比较,这很有趣。