具有多个类的函数实例

len*_*den -1 haskell functional-programming

我想为我的自定义数据类型实现幂函数。我的意思是具有以下签名的功率 (^):

(^) :: (Num a, Integral b) => a -> b -> a
Run Code Online (Sandbox Code Playgroud)

我的意思是我的数据类型MyData应该是 instance of Num,所以我可以写

x :: MyData
...
y = x ^ b
Run Code Online (Sandbox Code Playgroud)

其中 b 是一些Integral。当我们需要一个类的功能时,这很容易

(+), (-), (*) :: (Num a) => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

我们只是写

instance Num MyData where
  (*) x y = someFunc x y
Run Code Online (Sandbox Code Playgroud)

但我不知道如何定义它,因为还有Integral b. 这种语法应该是这样的

instance (Integral b) => Num MyData b where
  (^) x y = someFunc x y
Run Code Online (Sandbox Code Playgroud)

但是我已经尝试了一百种这样的变体,但没有任何效果。数小时的谷歌搜索也无济于事。

che*_*ner 5

你不必(^)为你的数据类型做任何定义;如果你的类型有一个Num实例,你可以x ^ b免费获得,因为它(^)是为具有实例的任何类型定义的Num。(它基本上只是调用*了很多。)

请注意,(^)不是Numor的成员Integral;它只是一个独立的函数,其类型受两个类的约束。

来自https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Real.html#%5E

(^) :: (Num a, Integral b) => a -> b -> a
x0 ^ y0 | y0 < 0    = errorWithoutStackTrace "Negative exponent"
        | y0 == 0   = 1
        | otherwise = f x0 y0
    where -- f : x0 ^ y0 = x ^ y
          f x y | even y    = f (x * x) (y `quot` 2)
                | y == 1    = x
                | otherwise = g (x * x) (y `quot` 2) x         -- See Note [Half of y - 1]
          -- g : x0 ^ y0 = (x ^ y) * z
          g x y z | even y = g (x * x) (y `quot` 2) z
                  | y == 1 = x * z
                  | otherwise = g (x * x) (y `quot` 2) (x * z) -- See Note [Half of y - 1]
Run Code Online (Sandbox Code Playgroud)

x0是你的MyData价值;唯一(^)能做的事情x0(因为它被作为x参数传递给for g)是将它自身相乘,所以(^)只要你(*)在你的Num实例中定义,技术上就可以工作。