为什么 Complex 的乘法实现需要 RealFloat?

Why does the multiplication implementation for Complex require a RealFloat?

在 GHCi 中,可以找到以下内容:

 import Data.Complex
 :t 2 * (3 :+ 4)
2 * (3 :+ 4) :: RealFloat a => Complex a
 :t (* (3 :+ 4))
(* (3 :+ 4)) :: RealFloat a -> Complex a -> Complex a

但是:

 :t fmap (* 2) (3 :+ 4)
fmap (* 2) (3 :+ 4) :: Num a => Complex a -> Complex a

现在,为什么会这样?只是 Num a => Complex a 下的 fromInteger 有类型 RealFloat a => a -> Complex a 吗?如果是,为什么?

问题是 Complex a 仅在 a 实例化 RealFloat 时才实例化 Num。即 Num 实例定义为:

instance RealFloat a => Num (Complex a) where
    ...

由于 *Num 定义,如果 Complex aNum 的实例,则只能在 Complex a 上使用 *,即如果 aRealFloat.

的实例

那么为什么 Num 实例有这个限制?

是因为这个方法:

abs :: a -> a

复数的绝对值可以是非整数,即使它的两个分量都是整数。例如1+1i的绝对值为√2。因此无法定义方法 abs :: Complex Integer -> Complex Integer(至少不能以产生正确结果的方式),因此无法定义 Num (Complex Integer) 的完整实例。所以只有 RealFloats.

signum方法也是如此。