Haskell,函数在使用数字时有效,但在变量时无效

时间:2014-07-04 12:10:13

标签: variables haskell types literals

我正在使用ghci而我遇到了一个函数问题,无法获取数字因子。

我想要的代码是:

let factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]

当我点击输入时它并没有抱怨,但是一旦我尝试使用它(在这种情况下为66),我收到此错误消息:

Ambiguous type variable 't0' in the constraints:
  (Integral t0)
    arising from a use of 'factors' at <interactive>:30:1-10
  (Num t0) arising from the literal '66' at <interactive>:30:12-13
  (RealFrac t0)
    arising from a use of 'factors' at <interactive:30:1-10
  Probable fix: add a type signature that fixes these type variable(s)
  In the expression: factors 66
  In the equation for 'it': it = factors 66

以下代码完美无缺:

let factorsOfSixtySix = [x | x <- [1..truncate (66/2)], mod 66 x == 0]

我是haskell的新手,在查找了类型和类型类后,我仍然不确定我的意图。

3 个答案:

答案 0 :(得分:3)

使用div代替整数除法:

let factors n = [x | x <- [1.. n `div` 2], mod n x == 0]

您的代码中的问题是,/要求RealFrac n类型mod Integral n。这在定义期间很好,但是你不能选择适合两种约束的类型。

另一种选择可能是在使用mod之前截断factors 6.5,但更麻烦。毕竟,你不想打电话给let factors n = [x | x <- [1..truncate (n/2)], mod (truncate n) x == 0] ,对吗? ; - )

{{1}}

答案 1 :(得分:0)

如果在此顶级绑定(惯用的Haskell)上放置类型注释,则会得到不同的,可能更有用的错误消息。

GHCi> let factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]
GHCi> :t factors
factors :: (Integral t, RealFrac t) => t -> [t]
GHCi> let { factors :: Double -> [Double]; factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]; }

<interactive>:30:64:
    No instance for (Integral Double) arising from a use of `truncate'
    Possible fix: add an instance declaration for (Integral Double)
    In the expression: truncate (n / 2)
    In the expression: [1 .. truncate (n / 2)]
    In a stmt of a list comprehension: x <- [1 .. truncate (n / 2)]
GHCi> let { factors :: Integer -> [Integer]; factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]; }

<interactive>:31:66:
    No instance for (RealFrac Integer) arising from a use of `truncate'
    Possible fix: add an instance declaration for (RealFrac Integer)
    In the expression: truncate (n / 2)
    In the expression: [1 .. truncate (n / 2)]
    In a stmt of a list comprehension: x <- [1 .. truncate (n / 2)]

<interactive>:31:77:
    No instance for (Fractional Integer) arising from a use of `/'
    Possible fix: add an instance declaration for (Fractional Integer)
    In the first argument of `truncate', namely `(n / 2)'
    In the expression: truncate (n / 2)
    In the expression: [1 .. truncate (n / 2)]

答案 2 :(得分:0)

我是Haskell的新手所以请原谅我在这里提出答案的勇气,但最近我做了以下这样的事情;

factors :: Int -> [Int]
factors n = f' ++ [n `div` x | x <- tail f', x /= exc]
            where lim = truncate (sqrt (fromIntegral n))
                  exc = ceiling (sqrt (fromIntegral n))
                  f'  = [x | x <- [1..lim], n `mod` x == 0]

我相信它更有效率。如果你愿意,你会注意到;

sum (factors 33550336)