1

这是一个接受一对 Integral 值并将它们相除的函数:

divide_v1 :: Integral a => (a, a) -> a
divide_v1 (m, n) = (m + n) `div` 2

我使用一对 Integral 值调用该函数,它按预期工作:

divide_v1 (1, 3)

伟大的。如果我的数字总是积分,那就完美了。

这是一个函数,它采用一对分数值并将它们相除:

divide_v2 :: Fractional a => (a, a) -> a
divide_v2 (m, n) = (m + n) / 2

我用一对分数值调用该函数,它按预期工作:

divide_v2 (1.0, 3.0)

伟大的。如果我的数字总是小数,那就完美了。

我想要一个无论数字是整数还是分数都可以工作的函数:

divide_v3 :: Num a => (a, a) -> a
divide_v3 (m, n) = (m + n) ___ 2

我为_使用什么运算符?

4

2 回答 2

4

为了扩展 AndrewC 所说的内容, div 与 / 没有相同的属性。例如,在数学中,如果 a 除以 b = c,则 c 乘以 b == a。当使用 Double 和 Float 等类型时,操作 / 和 * 满足此属性(在类型的准确性允许的范围内)。但是当将 div 与 Ints 一起使用时,该属性不成立。5 div3 = 1,但 1*3 /= 5!因此,如果您想对多种数字类型使用相同的“除法运算”,您需要考虑您希望它如何表现。此外,您几乎肯定不想使用相同的运算符 /,因为这会产生误导。

如果您希望您的“除法操作”返回与其操作数相同的类型,这是实现此目的的一种方法:

class Divideable a where
  mydiv :: a -> a -> a

instance Divideable Int where
  mydiv = div

instance Divideable Double where
  mydiv = (/)

在 GHCi 中,它看起来像这样:

λ> 5 `mydiv` 3 :: Int
1
λ> 5 `mydiv` 3 :: Double
1.6666666666666667
λ> 5.0 `mydiv` 3.0 :: Double
1.6666666666666667

另一方面,如果你想做“真正的”除法,你需要像这样转换整数类型:

class Divideable2 a where
  mydiv2 :: a -> a -> Double

instance Divideable2 Int where
  mydiv2 a b = fromIntegral a / fromIntegral b

instance Divideable2 Double where
  mydiv2 = (/)

在 GHCi 中,这给出:

λ> 5 `mydiv2` 3
1.6666666666666667
λ> 5.0 `mydiv2` 3.0
1.6666666666666667
于 2012-10-24T13:11:31.337 回答
1

我认为您正在寻找允许隐式类型强制的关联类型,并且在这里得到了很好的解释。下面是双精度数和整数相加的示例。

class Add a b where
    type SumTy a b
    add :: a -> b -> SumTy a b

instance Add Integer Double where
    type SumTy Integer Double = Double
    add x y = fromIntegral x + y

instance Add Double Integer where
     type SumTy Double Integer = Double
     add x y = x + fromIntegral y

instance (Num a) => Add a a where
     type SumTy a a = a
     add x y = x + y
于 2012-10-24T11:24:32.527 回答