How to overload the power function (^) in haskell?
I'm tring to implement a following datatype:
data Inter = Inter Double Double deriving (Read, Eq)
and I implemented (+)
,(-)
,(*)
and (/)
,
but the potentiation to a integer power(^)
should not be repeated multiplication for this datatype.
Is there a way for me to implement this function just like i did to the others?
haskell types
add a comment |
I'm tring to implement a following datatype:
data Inter = Inter Double Double deriving (Read, Eq)
and I implemented (+)
,(-)
,(*)
and (/)
,
but the potentiation to a integer power(^)
should not be repeated multiplication for this datatype.
Is there a way for me to implement this function just like i did to the others?
haskell types
3
Looking at the source, if you've already implemented theNum
instance, then(^) :: (Num a, Integral b) -> a -> b -> a
comes automatically. You cannot redefine it for a particular type because it's not part of any typeclass.
– AJFarmar
Dec 27 '18 at 2:20
1
You cannot overload it, since it is not a method of type class. but you still can implement your own version(^)
operator by hiding(^)
fromPrelude
usingimport Prelude hiding ((^))
in the module you define it.
– assembly.jc
Dec 27 '18 at 3:02
@assembly.jc would you need to use -XNoImplicitPrelude then?
– Eliza Brandt
Dec 27 '18 at 4:05
My opinion: if your operation is not repeated multiplication, then it should not be called(^)
.
– Daniel Wagner
Dec 27 '18 at 4:20
@DanielWagner It could be repeated multiplication, but with a faster implementation (e.g. if*
is idempotent). Or in an AST datatype you may want to represent powers with a separate constructor, and I think it still makes sense to use(^)
for this case.
– Alexey Romanov
Dec 27 '18 at 6:52
add a comment |
I'm tring to implement a following datatype:
data Inter = Inter Double Double deriving (Read, Eq)
and I implemented (+)
,(-)
,(*)
and (/)
,
but the potentiation to a integer power(^)
should not be repeated multiplication for this datatype.
Is there a way for me to implement this function just like i did to the others?
haskell types
I'm tring to implement a following datatype:
data Inter = Inter Double Double deriving (Read, Eq)
and I implemented (+)
,(-)
,(*)
and (/)
,
but the potentiation to a integer power(^)
should not be repeated multiplication for this datatype.
Is there a way for me to implement this function just like i did to the others?
haskell types
haskell types
asked Dec 27 '18 at 2:12
Leonardo Moraes
304
304
3
Looking at the source, if you've already implemented theNum
instance, then(^) :: (Num a, Integral b) -> a -> b -> a
comes automatically. You cannot redefine it for a particular type because it's not part of any typeclass.
– AJFarmar
Dec 27 '18 at 2:20
1
You cannot overload it, since it is not a method of type class. but you still can implement your own version(^)
operator by hiding(^)
fromPrelude
usingimport Prelude hiding ((^))
in the module you define it.
– assembly.jc
Dec 27 '18 at 3:02
@assembly.jc would you need to use -XNoImplicitPrelude then?
– Eliza Brandt
Dec 27 '18 at 4:05
My opinion: if your operation is not repeated multiplication, then it should not be called(^)
.
– Daniel Wagner
Dec 27 '18 at 4:20
@DanielWagner It could be repeated multiplication, but with a faster implementation (e.g. if*
is idempotent). Or in an AST datatype you may want to represent powers with a separate constructor, and I think it still makes sense to use(^)
for this case.
– Alexey Romanov
Dec 27 '18 at 6:52
add a comment |
3
Looking at the source, if you've already implemented theNum
instance, then(^) :: (Num a, Integral b) -> a -> b -> a
comes automatically. You cannot redefine it for a particular type because it's not part of any typeclass.
– AJFarmar
Dec 27 '18 at 2:20
1
You cannot overload it, since it is not a method of type class. but you still can implement your own version(^)
operator by hiding(^)
fromPrelude
usingimport Prelude hiding ((^))
in the module you define it.
– assembly.jc
Dec 27 '18 at 3:02
@assembly.jc would you need to use -XNoImplicitPrelude then?
– Eliza Brandt
Dec 27 '18 at 4:05
My opinion: if your operation is not repeated multiplication, then it should not be called(^)
.
– Daniel Wagner
Dec 27 '18 at 4:20
@DanielWagner It could be repeated multiplication, but with a faster implementation (e.g. if*
is idempotent). Or in an AST datatype you may want to represent powers with a separate constructor, and I think it still makes sense to use(^)
for this case.
– Alexey Romanov
Dec 27 '18 at 6:52
3
3
Looking at the source, if you've already implemented the
Num
instance, then (^) :: (Num a, Integral b) -> a -> b -> a
comes automatically. You cannot redefine it for a particular type because it's not part of any typeclass.– AJFarmar
Dec 27 '18 at 2:20
Looking at the source, if you've already implemented the
Num
instance, then (^) :: (Num a, Integral b) -> a -> b -> a
comes automatically. You cannot redefine it for a particular type because it's not part of any typeclass.– AJFarmar
Dec 27 '18 at 2:20
1
1
You cannot overload it, since it is not a method of type class. but you still can implement your own version
(^)
operator by hiding (^)
from Prelude
using import Prelude hiding ((^))
in the module you define it.– assembly.jc
Dec 27 '18 at 3:02
You cannot overload it, since it is not a method of type class. but you still can implement your own version
(^)
operator by hiding (^)
from Prelude
using import Prelude hiding ((^))
in the module you define it.– assembly.jc
Dec 27 '18 at 3:02
@assembly.jc would you need to use -XNoImplicitPrelude then?
– Eliza Brandt
Dec 27 '18 at 4:05
@assembly.jc would you need to use -XNoImplicitPrelude then?
– Eliza Brandt
Dec 27 '18 at 4:05
My opinion: if your operation is not repeated multiplication, then it should not be called
(^)
.– Daniel Wagner
Dec 27 '18 at 4:20
My opinion: if your operation is not repeated multiplication, then it should not be called
(^)
.– Daniel Wagner
Dec 27 '18 at 4:20
@DanielWagner It could be repeated multiplication, but with a faster implementation (e.g. if
*
is idempotent). Or in an AST datatype you may want to represent powers with a separate constructor, and I think it still makes sense to use (^)
for this case.– Alexey Romanov
Dec 27 '18 at 6:52
@DanielWagner It could be repeated multiplication, but with a faster implementation (e.g. if
*
is idempotent). Or in an AST datatype you may want to represent powers with a separate constructor, and I think it still makes sense to use (^)
for this case.– Alexey Romanov
Dec 27 '18 at 6:52
add a comment |
2 Answers
2
active
oldest
votes
^
defined in prelude you can't overload it. It doesn't belong to any typeclass.
It is defined using *
from Num
.
See source.
add a comment |
Considering that your implementation of (^)
will be an optimization and will produce equivalent results, what you can do is define your faster version in the same module as your Num
instance and call it say interPower
. Then you can try adding some rewrite rules, which in theory should fire, but I'd suggest compiling a test program with -ddump-simpl-stats
and confirming that they do indeed fire before the rules from base
do:
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
#-}
Edit
Just tried above approach and it indeed overloaded the usage of (^)
:
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))
resulted in these rules to fire when compiled with ghc -O2 -ddump-simpl-stats -ddump-to-file
. See 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
...
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53939041%2fhow-to-overload-the-power-function-in-haskell%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
^
defined in prelude you can't overload it. It doesn't belong to any typeclass.
It is defined using *
from Num
.
See source.
add a comment |
^
defined in prelude you can't overload it. It doesn't belong to any typeclass.
It is defined using *
from Num
.
See source.
add a comment |
^
defined in prelude you can't overload it. It doesn't belong to any typeclass.
It is defined using *
from Num
.
See source.
^
defined in prelude you can't overload it. It doesn't belong to any typeclass.
It is defined using *
from Num
.
See source.
answered Dec 27 '18 at 2:58
talex
9,4731546
9,4731546
add a comment |
add a comment |
Considering that your implementation of (^)
will be an optimization and will produce equivalent results, what you can do is define your faster version in the same module as your Num
instance and call it say interPower
. Then you can try adding some rewrite rules, which in theory should fire, but I'd suggest compiling a test program with -ddump-simpl-stats
and confirming that they do indeed fire before the rules from base
do:
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
#-}
Edit
Just tried above approach and it indeed overloaded the usage of (^)
:
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))
resulted in these rules to fire when compiled with ghc -O2 -ddump-simpl-stats -ddump-to-file
. See 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
...
add a comment |
Considering that your implementation of (^)
will be an optimization and will produce equivalent results, what you can do is define your faster version in the same module as your Num
instance and call it say interPower
. Then you can try adding some rewrite rules, which in theory should fire, but I'd suggest compiling a test program with -ddump-simpl-stats
and confirming that they do indeed fire before the rules from base
do:
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
#-}
Edit
Just tried above approach and it indeed overloaded the usage of (^)
:
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))
resulted in these rules to fire when compiled with ghc -O2 -ddump-simpl-stats -ddump-to-file
. See 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
...
add a comment |
Considering that your implementation of (^)
will be an optimization and will produce equivalent results, what you can do is define your faster version in the same module as your Num
instance and call it say interPower
. Then you can try adding some rewrite rules, which in theory should fire, but I'd suggest compiling a test program with -ddump-simpl-stats
and confirming that they do indeed fire before the rules from base
do:
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
#-}
Edit
Just tried above approach and it indeed overloaded the usage of (^)
:
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))
resulted in these rules to fire when compiled with ghc -O2 -ddump-simpl-stats -ddump-to-file
. See 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
...
Considering that your implementation of (^)
will be an optimization and will produce equivalent results, what you can do is define your faster version in the same module as your Num
instance and call it say interPower
. Then you can try adding some rewrite rules, which in theory should fire, but I'd suggest compiling a test program with -ddump-simpl-stats
and confirming that they do indeed fire before the rules from base
do:
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
#-}
Edit
Just tried above approach and it indeed overloaded the usage of (^)
:
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))
resulted in these rules to fire when compiled with ghc -O2 -ddump-simpl-stats -ddump-to-file
. See 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
...
edited Dec 27 '18 at 16:29
answered Dec 27 '18 at 15:01
lehins
5,91521936
5,91521936
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53939041%2fhow-to-overload-the-power-function-in-haskell%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
Looking at the source, if you've already implemented the
Num
instance, then(^) :: (Num a, Integral b) -> a -> b -> a
comes automatically. You cannot redefine it for a particular type because it's not part of any typeclass.– AJFarmar
Dec 27 '18 at 2:20
1
You cannot overload it, since it is not a method of type class. but you still can implement your own version
(^)
operator by hiding(^)
fromPrelude
usingimport Prelude hiding ((^))
in the module you define it.– assembly.jc
Dec 27 '18 at 3:02
@assembly.jc would you need to use -XNoImplicitPrelude then?
– Eliza Brandt
Dec 27 '18 at 4:05
My opinion: if your operation is not repeated multiplication, then it should not be called
(^)
.– Daniel Wagner
Dec 27 '18 at 4:20
@DanielWagner It could be repeated multiplication, but with a faster implementation (e.g. if
*
is idempotent). Or in an AST datatype you may want to represent powers with a separate constructor, and I think it still makes sense to use(^)
for this case.– Alexey Romanov
Dec 27 '18 at 6:52