I want to redefine several arithmetic operators in Haskell in order to make them more extensible and generic.
E.g.
class Mul a b c | a b -> c where
(*) :: a -> b -> c
This seems to work in combination with
import Prelude hiding ((*))
hiding the standard *
operator. But of course all usual multiplications have to work as well, so I'd have to define something like
instance (Num t) => Mul t t t where
(*) = ??
How can I access the original *
operator (Prelude.(*)
doesn't work) here and how do I have to define the instance type such that 1 * 1
doesn't conflict with the Monomorpism Restriction?
Edit -
import qualified
is a good tip, thanks.
But unfortunately this forced me to bring all standard methods into scope explicitly. I just want to have the possibility of redefining certain bindings leaving the rest unchanged.
So is there a combination of both? Something like
import Prelude qualified ((*))
The ++ operator is the list concatenation operator which takes two lists as operands and "combines" them into a single list.
(->) is often called the "function arrow" or "function type constructor", and while it does have some special syntax, there's not that much special about it. It's essentially an infix type operator. Give it two types, and it gives you the type of functions between those types.
in goes along with let to name one or more local expressions in a pure function.
Haskell provides special syntax to support infix notation. An operator is a function that can be applied using infix syntax (Section 3.4), or partially applied using a section (Section 3.5).
Answering the edited question:
You can do
import Prelude hiding ((*))
import qualified Prelude as P
to gain access to all Prelude functions except (*)
in the usual way and to (*)
via the P
prefix:
x = 5 + 3 -- works
y = 5 P.* 3 -- works
z = 5 * 3 -- complains about * not being in scope
The instance
instance (Num t) => Mul t t t where
(*) = ??
Will largely defeat the purpose of having defined Mul t t t
in the first place, without abusing extensions to allow {-# LANGUAGE OverlappingInstances #-}
.
Unfortunately the 'right' if painful answer is to go through instance by instance and do
import Prelude hiding ((*))
import qualified Prelude
instance Mul Int Int Int where
(*) = (Prelude.*)
instance Mul Double Double Double where
(*) = (Prelude.*)
instance Mul Int Double Double where
...
instance Mul (Complex Float) (Complex Double) (Complex Double)
...
Otherwise the way that instance heads get resolved in the compiler (no backtracking is done) will probably make your novel instances cause compilation to blow up when you go to actually use them.
That said, you can at least ease the pain for instances you didn't think of:
newtype Other a = Other a
instance Num a => Mul (Other a) (Other a) (Other a) where
Other a * Other b = Other (a Prelude.* b)
This will at least let them just use your newtype wrapper if they don't want to go and define Mul and all of your other classes themselves.
There have been a few attempts to do things like this.
Firstly,
How can I access the original * operator (Prelude.(*) doesn't work)
You'll need to:
import qualified Prelude
now you can use e.g. (Prelude.*). This is less aggressive than "LANGUAGE NoImplicitPrelude" which will also cause local uses of >>= and so on to be rebound to your definitions.
Here are examples of other people's alternative preludes:
I can answer the first question. Hiding the (*) operator really hides it, so you can't get at it. However, you can import Prelude qualified:
import qualified Prelude as P
foo = 3 P.* 14 -- == 42
I think that that does what you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With