gpt4 book ai didi

haskell - 同一实例的不同类型约束

转载 作者:行者123 更新时间:2023-12-02 12:10:18 24 4
gpt4 key购买 nike

我正在定义自己的复数数据类型作为学习练习,但在重载 abs 以及 Num 的其他成员时遇到了麻烦。据我所知,每个类型类只允许一个实例定义,但如果可以的话,我会做这样的事情:

instance Num a => Num (Complex a) where
(+) (Complex ra ia) (Complex rb ib) = Complex (ra + rb) (ia + ib)
(-) (Complex ra ia) (Complex rb ib) = Complex (ra - rb) (ia - ib)
(*) (Complex ra ia) (Complex rb ib) = Complex (ra*rb - ia*ib) (ra*ib + rb*ia)
fromInteger r = Complex (fromInteger r) 0

instance Floating a => Num (Complex a) where
abs (Complex r i) = Complex (sqrt $ r^2 + i^2) 0

instance Floating a => Floating (Complex a) where
abs (Complex r i) = Complex (sqrt $ r^2 + i^2) 0

因为除了 abs 之外,没有任何成员需要 Floating 类型,并且我不想将它们限制为仅 Floating 类型,但 abs 函数非常重要,我不想不必要地排除它。
有什么方法可以让函数 (+)(-)(*) 适用于所有数字类型,同时仍然实现abs

根据7.6.3.4. Overlapping instances在 GHC 系统指南中,如果多个实例在上下文之外的类型约束(?)不同(例如实例 C [a] 和实例 C [Int] ),则它们可以重叠>),编译器为给定情况选择最具体的实例,但它没有提及仅上下文不同的任何内容(例如 instance C [a]instance Integral a = > C [a])。

最佳答案

这里的主要痛苦来源是 Prelude 的数字层次结构被定义得不太复杂 - 对于大多数事情来说,它工作得很好。这是那些实际上并不存在的边缘情况之一(尽管正如 @leftaroundabout 指出的那样,我不确定 Complex 是否有很多应用程序,而不是 Floating 的东西。 )。

您的选择是

  • 添加Floating a Num (Complex a) 的约束。这对我来说是最自然的,从类型类的角度来看也是最有意义的——在 instance Num a => Num (Complex a) 中进行硬塞。打破了Num抽象,因为它没有 abs 的概念.
  • 使用更细粒度的数字层次结构。 numeric-prelude 我想到了。在其中,您将找到以下内容(分布在多个模块中):

    class (Field.C a) => Algebraic.C a where
    sqrt :: a -> a

    class (Ring.C a) => Field.C a where
    (/) :: a -> a -> a
    recip :: a -> a
    fromRational' :: Rational -> a
    (^-) :: a -> Integer -> a

    class (Ring.C a) => Absolute.C a where
    abs :: a -> a
    signum :: a -> a

    class (Additive.C a) => Ring.C a where
    (*) :: a -> a -> a
    one :: a
    fromInteger :: Integer -> a
    (^) :: a -> Integer -> a

    class Additive.C a where
    zero :: a
    (+), (-) :: a -> a -> a
    negate :: a -> a

    就您而言,您将创建实例 instance Additive.C a => Additive.C (Complex a) , instance Ring.C a => Ring.C (Complex a) ,和instance Algebraic.C a => Absolute.C (Complex a) .

  • 如果我还没有说服你放弃这种疯狂,请随时查看 this page on advanced overlap 。除了复杂且样板代码繁重(并且需要打开大量语言扩展)之外,此解决方案还不太通用(您仍然需要手动选择哪些类型进入哪个实例)。

关于haskell - 同一实例的不同类型约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42067603/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com