Haskell 具有多个类的函数的实例
我想实现自定义数据类型的幂函数。我是指具有以下签名的电源(^):Haskell 具有多个类的函数的实例,haskell,functional-programming,Haskell,Functional Programming,我想实现自定义数据类型的幂函数。我是指具有以下签名的电源(^): (^) :: (Num a, Integral b) => a -> b -> a 我的意思是,我的数据类型MyData应该是Num的实例,这样我就可以编写 x :: MyData ... y = x ^ b 其中b是一些积分。当我们需要一个类的函数,比如 (+), (-), (*) :: (Num a) => a -> a -> a 我们只是写信 instance Num MyData
(^) :: (Num a, Integral b) => a -> b -> a
我的意思是,我的数据类型MyData
应该是Num
的实例,这样我就可以编写
x :: MyData
...
y = x ^ b
其中b是一些积分。当我们需要一个类的函数,比如
(+), (-), (*) :: (Num a) => a -> a -> a
我们只是写信
instance Num MyData where
(*) x y = someFunc x y
但是考虑到还有积分b,我不知道如何定义它。这种语法应该是
instance (Integral b) => Num MyData b where
(^) x y = someFunc x y
但我已经尝试过一百种这样的变化,但都没有效果。数小时的谷歌搜索也无济于事。您不必做任何事情来定义数据类型的
(^)
;如果您的类型有一个Num
实例,您将免费获得x^b
,因为(^)
是为具有Num
实例的任何类型定义的。(它基本上只是调用了很多*
)
请注意,(^)
不是Num
或Integral
的成员;它只是一个独立函数,其类型受两个类的约束
从
(^):(数值a,整数b)=>a->b->a
x0^y0 | y0<0=错误,无跟踪“负指数”
|y0==0=1
|否则=f x0 y0
式中--f:x0^y0=x^y
f x y |偶y=f(x*x)(y`quot`2)
|y==1=x
|否则=g(x*x)(y`quot`2)x——见注释[y-1的一半]
--g:x0^y0=(x^y)*z
g x y z |偶y=g(x*x)(y`quot`2)z
|y==1=x*z
|否则=g(x*x)(y`quot`2)(x*z)——见注释[y-1的一半]
x0
是您的MyData
值;(^)
对x0
所做的唯一一件事就是将其自身相乘(因为它被作为x
参数传递给f
或g
),所以从技术上讲,(^)
只要定义了(*)
在Num
实例中。积分约束与Num
约束无关。如果为MyData
定义一个Num
实例,那么只要b
是整数,就可以编写x^b
(^)
将使用您的Num
实例,而不是相反。您的类型实际上是数字类型,还是您只想将(x^y)
作为编写“dox
y
时间”的简短方式?如果是前者,您应该实现Num的所有功能,而不仅仅是一个功能,如果是后者,您应该使用除(^)
之外的其他功能。例如,半群上诉,如果你想要一个像stimes
这样的效果。如果你想使用MyData
作为指数,那么你还需要为MyData
定义一个整数
实例。你不需要定义(^)
;只要您有MyData
的Num
实例,您就可以免费获得它。此外,您的错误消息(类“Y”中没有成员“x”)似乎来自Hugs。你可能想考虑切换到GHC。拥抱真的很老了(自从上次官方发布以来已经十年多了),获得帮助是很困难的。非常感谢!它起作用了。不幸的是,这是绝对不明显的:(我认为正确的方法是一些bonecrushing实例语法变体
(^) :: (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]