【问题标题】:Instance of Complex Double复双的实例
【发布时间】:2018-02-17 23:43:42
【问题描述】:

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

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

这将用于计算标准偏差(我知道为给出实数的复数定义了标准偏差,但在我的情况下“独立”更有意义)。

但我在某些实例声明方面遇到了问题。特别是其中一项操作应该是“乘以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 -&gt; Complex Double -&gt; Complex Double,但是标准差必须为不同的结构单独定义。

有什么想法吗?

【问题讨论】:

  • 只需使用 FlexibleInstances。

标签: class haskell types instance complex-numbers


【解决方案1】:

作为 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

【讨论】:

  • 不错!我喜欢最后一个选项。但是为什么编译器不抱怨这个呢?它不知道规模是在给定的a(例如Int)中定义的吗?如果您稍后在可能发生这种情况的上下文中使用它,它会抱怨吗?我可能应该阅读组合实例..
  • @jorgen 注意(Separate a) =&gt; 子句,它保证scale 是为a 定义的。这个实例说Complex preserves Separateness.
  • 啊,有道理
  • @VanessaMcHale works for me,你得到/期待什么错误?
  • @VanessaMcHale 哦,你写了另一个答案。应用程序的绑定也比操作符部分更紧密。正如2 * realToFrac d 被解析为2 * (realToFrac d)(* realToFrac d) 被解析为(* (realToFrac d))。我怀疑你可能来自 lisp 世界,那里的语法意味着完全不同的东西。
【解决方案2】:

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

我会重写实例如下:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 2016-01-15
    • 2016-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多