在范围内使用(ceiling。sqrt)会导致错误

时间:2018-02-10 08:40:49

标签: haskell

我几天前刚刚开始学习Hasekll,当我在尝试快速和脏的素数检查器时遇到一个神秘的错误时,我正在玩范围。

isprime n = all ((<) 0)  [n `rem` k | k <- [2..n-1]] -- okay
isprime' n = all ((<) 0)  [n `rem` k | k <- [2..(ceiling . sqrt) n]] -- compiles but busted

示例:

Prelude> isprime 19
True

Prelude> isprime' 19

<interactive>:46:1: error:
    • Ambiguous type variable ‘a0’ arising from a use of ‘isprime'’
      prevents the constraint ‘(Floating a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance Floating Double -- Defined in ‘GHC.Float’
        instance Floating Float -- Defined in ‘GHC.Float’
    • In the expression: isprime' 19
      In an equation for ‘it’: it = isprime' 19

<interactive>:46:10: error:
    • Ambiguous type variable ‘a0’ arising from the literal ‘19’
      prevents the constraint ‘(Num a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance Num Integer -- Defined in ‘GHC.Num’
        instance Num Double -- Defined in ‘GHC.Float’
        instance Num Float -- Defined in ‘GHC.Float’
        ...plus two others
        ...plus one instance involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the first argument of ‘isprime'’, namely ‘19’
      In the expression: isprime' 19
      In an equation for ‘it’: it = isprime' 19

所以我检查了以下内容,结果都是预期的结果。

Prelude> [rem 19 k | k <- [2.. 19-1]] 
[1,1,3,4,1,5,3,1,9,8,7,6,5,4,3,2,1]

Prelude> [rem 19 k | k <- [2..(ceiling . sqrt) 19]] 
[1,1,3,4]

任何人都可以帮我理解这个问题吗?如果在线Haskell教程中有一个很好的部分,会很感激指针。谢谢!

1 个答案:

答案 0 :(得分:1)

使用显式转换:

[2..(ceiling . sqrt . fromIntegral) n]

否则,您在sqrt类型上调用n,强制该类型为Floating。其余代码已要求n具有某种Integral类型。

无法满足这两个要求:标准数字类型可以是浮点数,也可以是固定点(Integral,大致)。

如果您开始使用类型注释编写函数,这也会有很大帮助。这可以防止GHC推断出一种非预期的类型 - 当这种情况发生时,很快就会发现错误,从而导致混淆。