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

如何在haskell中重载幂函数(^)?,haskell,types,Haskell,Types,我尝试实现以下数据类型: data Inter = Inter Double Double deriving (Read, Eq) 我实现了+、-、*和/, 但是,对于该数据类型,整数幂的增强不应重复乘法。 有没有一种方法可以让我像对其他人一样实现此功能?^在prelude中定义,您不能重载它。它不属于任何类型类 它是使用*from Num定义的 请参阅。考虑到^的实现将是一种优化,并将产生相同的结果,您可以做的是在与Num实例相同的模块中定义更快的版本,并将其称为say interPower

我尝试实现以下数据类型:

data Inter = Inter Double Double deriving (Read, Eq)
我实现了+、-、*和/, 但是,对于该数据类型,整数幂的增强不应重复乘法。 有没有一种方法可以让我像对其他人一样实现此功能?

^在prelude中定义,您不能重载它。它不属于任何类型类

它是使用*from Num定义的


请参阅。

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

编辑

刚刚尝试了上述方法,它确实超载了^:

导致在使用ghc-O2-ddump siml stats-ddump to file编译时触发这些规则。请参阅main.dump-siml-stats:


看看,如果您已经实现了Num实例,那么^::Num a,Integral b->a->b->a会自动出现。不能为特定类型重新定义它,因为它不是任何类型类的一部分。不能重载它,因为它不是类型类的方法。但是您仍然可以通过在您定义的模块中使用import Prelude hiding^从Prelude中隐藏^operator来实现您自己的版本^operator。@assembly.jc是否需要使用-XNoImplicitPrelude?我的意见是:如果您的操作不是重复乘法,那么它就不应该被称为^。@DanielWagner它可以是重复乘法,但是使用更快的实现,例如if*是幂等的。或者在AST数据类型中,您可能希望用单独的构造函数表示powers,我认为在这种情况下使用^。
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))
...
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
...