Haskell:使用(fromInteger(一个`div`b)/ 1 == a / b)作为守卫?

时间:2017-12-15 06:05:07

标签: haskell

我是Haskell的新手,我不明白为什么我的警卫不会接受它。这是我的代码。如果ba的分隔符,则应该触发警卫。

gCF :: Integer -> Integer -> Integer;
gCF n p
    | (p <= 0 || n <= 0) = error "Input should be positive"
    | (p > n) = f p n
    | otherwise = f n p
    where 
        f :: Integer -> Integer -> Integer;
        f a b
            | (fromInteger (a `div` b) / 1 == a / b) = b
            | otherwise = f a (b - 1)

这是显示的错误。

testscript.hs:168:28: error:
• No instance for (Fractional Integer) arising from a use of ‘/’
• In the first argument of ‘(==)’, namely
    ‘fromInteger (a `div` b) / 1’
  In the expression: (fromInteger (a `div` b) / 1 == a / b)
  In a stmt of a pattern guard for
                 an equation for ‘f’:
    (fromInteger (a `div` b) / 1 == a / b)
    |
168 |                         | (fromInteger (a `div` b) / 1 == a / b) =      b     |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^

2 个答案:

答案 0 :(得分:4)

我认为你让它变得更复杂,必要。在Int eger和Float世界之间转换数字可能很危险,因为它会引入舍入问题。

如果我理解正确,您想要a检查b是否可分割。您可以通过验证mod a b == 0来检查这一点,我们仍处于整数世界中。所以我们可以将程序重写为:

gCF :: Integer -> Integer -> Integer
gCF n p | p <= 0 || n <= 0 = error "Input should be positive"
        | p > n = f p n
        | otherwise = f n p
    where f a b | mod a b == 0 = b
                | otherwise = f a (b-1)

由于a在递归调用中没有变化,我们可以将其分解为:

gCF :: Integer -> Integer -> Integer
gCF n p | p <= 0 || n <= 0 = error "Input should be positive"
        | otherwise = f (min p n)
    where a = max p n
          f b | mod a b == 0 = b
              | otherwise = f (b-1)

我们还可以对签名进行概括,使其适用于任何Integral类型:

gCF :: Integral i => i -> i -> i
gCF n p | p <= 0 || n <= 0 = error "Input should be positive"
        | otherwise = f (min p n)
    where a = max p n
          f b | mod a b == 0 = b
              | otherwise = f (b-1)

答案 1 :(得分:0)

我找到了解决方案!

gCF :: Integer -> Integer -> Integer;
gCF n p
    | (p <= 0 || n <= 0) = error "Input should be positive"
    | (p > n) = floor (f (fromInteger p) (fromInteger n) (fromInteger n))
    | otherwise = floor (f (fromInteger n) (fromInteger p) (fromInteger p))
    where 
        f :: Float -> Float -> Float -> Float;
        f a b c
            | (fromInteger (floor (a / c)) == a / c) && (fromInteger (floor (b / c)) == b / c) = c
            | otherwise = f a b (c - 1)