Haskell - 添加类型类?

kar*_*oss 4 haskell operator-overloading typeclass

请考虑以下示例:

data Dot = Dot Double Double
data Vector = Vector Double Double
Run Code Online (Sandbox Code Playgroud)

首先,我想重载+运算符Vector.如果我想重载equality(==)运算符,我会写它像:

instance Eq Vector where ...blahblahblah
Run Code Online (Sandbox Code Playgroud)

但我无法找到是否有Add类型类使Vector行为类似于带有加法运算的类型.我甚至找不到Haskell类型类的完整列表,我只知道很少来自不同的教程.这样的清单是否存在?

另外,我可以重载+运营商添加VectorDot(它似乎相当合理的,不是吗?).

Bor*_*ris 13

发现函数属于哪个类型类(如果有)的信息的简单方法是使用GHCi:

Prelude> :i (+)
class (Eq a, Show a) => Num a where
  (+) :: a -> a -> a
  ...
        -- Defined in GHC.Num
infixl 6 +
Run Code Online (Sandbox Code Playgroud)


sep*_*p2k 7

Prelude中的operator +由类型类Num定义.但是顾名思义,这不仅定义了加法,还定义了许多其他数值运算(特别是其他算术运算符以及使用数字文字的能力),因此这不适合您的用例.

除非你想要隐藏Prelude的+运算符(这意味着你必须为Integer,Double等创建自己的Addable实例,如果你仍然希望能够在数字上使用+),就没有办法只为你的类型重载+ ).

  • 我认为如果你实现Num并留下所有运算符并且(+)未定义并不重要.在实践中,Haskell程序员有时会实现类型类,并留下一些他们不会使用未定义的方法. (3认同)

ham*_*mar 5

您可以为向量加法(以及其他有意义的运算符)写入instance Num Vector重载+.

instance Num Vector where
    (Vector x1 y1) + (Vector x2 y2) = Vector (x1 + x2) (y1 + y2)
    -- and so on
Run Code Online (Sandbox Code Playgroud)

但是,请注意+具有类型Num a => a -> a -> a,即两个操作数和结果都必须是相同的类型.这意味着你不能有一个Dot加一个Vector是一个Dot.

虽然你可以隐藏NumPrelude并指定自己的+,这很容易造成混乱,使其难以与常规的算术一起使用你的代码.

我建议您为矢量点添加定义自己的运算符,例如

(Dot x y) `offsetBy` (Vector dx dy) = Dot (x + dx) (y + dy)
Run Code Online (Sandbox Code Playgroud)

或者如果你喜欢更短的东西,可以使用符号.