如何在Haskell中重载幂函数(^)?

时间:2018-12-27 02:12:52

标签: haskell types

我正打算实现以下数据类型:

data Inter = Inter Double Double deriving (Read, Eq)

我实现了(+)(-)(*)(/), 但是对于此数据类型,不应重复乘幂为(^)的整数倍。 有没有办法像我对其他人一样实现此功能?

2 个答案:

答案 0 :(得分:2)

前奏中定义的

^不能使它过载。它不属于任何类型类。

使用*中的Num来定义。

请参见source

答案 1 :(得分:1)

考虑到(^)的实现是一种优化,并且 会产生等效的结果,您可以做的是在与Num相同的模块中定义更快的版本实例,并说interPower。然后,您可以尝试添加一些重写规则,理论上应该触发这些规则,但是我建议使用-ddump-simpl-stats编译测试程序,并确认它们确实在base的规则执行之前就已触发:

interPower :: Integral b => Inter -> b -> Inter
interPower = ...
{-# INLINABLE [1] interPower #-}

{-# RULES
"Inter^2/Int"     forall x. (x :: Inter) ^ (2 :: Int) = interPower x (2 :: Int)
"Inter^3/Int"     forall x. (x :: Inter) ^ (3 :: Int) = interPower x (3 :: Int)
"Inter^4/Int"     forall x. (x :: Inter) ^ (4 :: Int) = interPower x (4 :: Int)
"Inter^5/Int"     forall x. (x :: Inter) ^ (5 :: Int) = interPower x (5 :: Int)
"Inter^2/Integer" forall x. (x :: Inter) ^ (2 :: Integer) = interPower x (2 :: Int)
"Inter^3/Integer" forall x. (x :: Inter) ^ (3 :: Integer) = interPower x (3 :: Int)
"Inter^4/Integer" forall x. (x :: Inter) ^ (4 :: Integer) = interPower x (4 :: Int)
"Inter^5/Integer" forall x. (x :: Inter) ^ (5 :: Integer) = interPower x (5 :: Int)

"Inter^Int"       forall x y. (x :: Inter) ^ (y :: Int) = interPower x y
"Inter^Integer"   forall x y. (x :: Inter) ^ (y :: Integer) = interPower x y

  #-}

修改

只是尝试了上述方法,确实使(^)的使用超载:

print (x ^ (2 :: Int))
print (x ^ (3 :: Int))
print (x ^ (4 :: Int))
print (x ^ (5 :: Int))
print (x ^ (6 :: Int))
print (x ^ (2 :: Integer))
print (x ^ (3 :: Integer))
print (x ^ (4 :: Integer))
print (x ^ (5 :: Integer))
print (x ^ (6 :: Integer))

使用ghc -O2 -ddump-simpl-stats -ddump-to-file进行编译时会导致这些规则触发。参见main.dump-simpl-stats

...
1 Inter^2/Int
1 Inter^2/Integer
1 Inter^3/Int
1 Inter^3/Integer
1 Inter^4/Int
1 Inter^4/Integer
1 Inter^5/Int
1 Inter^5/Integer
1 Inter^Int
1 Inter^Integer
...