Complex Double 的实例

Instance of Complex Double

我正在写一个 class Separate ,它独立地对不同结构的 "parts" 执行某些操作;例如复数的实部和复数部分(稍后我也将需要它用于列表)。通过这种方式,我可以编写不关心它们正在作用于哪些结构的函数,但会以这种独立的方式进行。

这些功能应该在没有零件的结构上正常工作,例如Double

这将用于计算标准差(我知道有一个为复数定义的标准差,它给出了一个实数,但 "independent" 对我来说更有意义)。

但是我在某些实例声明方面遇到了问题。特别是其中一个操作应该是 "multiply with a Double",又名 scale:

class Separate a where
  scale :: Double -> a -> a

instance Separate Double where
  scale = (*)

instance (Floating a) => Separate (Complex a) where
  d `scale` z = (*d) <$> z

这当然不能编译,因为 * 没有在 Double 和一般 Floating a 之间定义。但是我不能直接定义instance Separate (Complex Double) where....

我可以只写一个函数 Double -> Complex Double -> Complex Double 没有 class 但是标准偏差必须为不同的结构单独定义。

有什么想法吗?

作为n.m。指出,如果您使用 FlexibleInstances 扩展,定义 instance Separate (Complex Double) 是完全没问题的,这是一个流行且无害的扩展。

但也有其他选择,例如:

instance (Floating a) => Separate (Complex a) where
    d `scale` z = (* realToFrac d) <$> z

和组合实例(the best kind of instance):

instance (Separate a) => Separate (Complex a) where
    d `scale` z = (d `scale`) <$> z

这是一个类型问题,而不是您处理实例的方式的问题。如您所说,(*) 未定义在 DoubleFloat 之间。但是,我们可以轻松地在 DoubleFloat 之间进行转换,所以您很幸运!使用realToFrac,我们可以在各种小数类型之间进行转换。

我会重写实例如下:

instance (Floating a) -> Separate (Complex a) where
  d `scale` z = (* (realToFrac d)) <$> z