Is it possible to overload logical operators (&& eg.) In Haskell?
Haskell doesn't actually overload (= ad-hoc polymorphism) at all. +
, *
etc. - these are not functions, but methods of a class: their "overloading" is more like defining concrete descendants of an OO interface / purely abstract class than function overloading, for example, in C ++.
OTOH logical operators are just regular functions that are defined once and for all in the prelude.
However, in Haskell, infix operators are mostly treated as a special type of function name, they are not part of the actual syntax definition. Nothing prevents you from defining new, different operators with the same purpose, for example.
class Booly b where
true :: b
false :: b
(&&?) :: b -> b -> b
(||?) :: b -> b -> b
infixr 3 &&?
infixr 2 ||?
instance Booly Bool where
true = True
false = False
(&&?) = (&&)
(||?) = (||)
instance Booly MVBool where
true = ...
In fact, it is sufficient if the new names are eliminated using the module classifiers:
import Prelude hiding ((&&), (||))
import qualified Prelude
class Booly b where
true :: b
false :: b
(&&) :: b -> b -> b
(||) :: b -> b -> b
infixr 3 &&
infixr 2 ||
instance Booly Bool where
true = True
false = False
(&&) = (Prelude.&&)
(||) = (Prelude.||)
source to share
There is no such thing as monkey-like overriding in Haskell.
It is also impossible to connect an extension to something that was not created for the extension.
You can just shade the definition for example. &&
, but this 1) will not affect semantics &&
in other modules and 2) will be confusing.
So, I would use something simple:
-- laws should be defined for the class and instances QuickChecked/proved against these laws class Logic a where (&.&) :: a -> a -> a (|.|) :: a -> a -> a ... instance Logic Bool where (&.&) = (&&) (|.|) = (||) data MultiBool = False' | True' | Perhaps | CouldBe | Possibly | Unlikely instance Logic MultiBool where ...
source to share
No, It is Immpossible. The type &&
is Bool -> Bool -> Bool
, and Haskell does not allow ad-hoc overloading. You can shadow the declaration, but then you cannot use the operator for both boolean and your mvl values ββin the same unskilled module.
I recommend you define similar operators such as &&?
for your mvls.
source to share
(&&)
defined as
(&&) :: Bool -> Bool -> Bool
Therefore, if you do not download Prelude
or load it, you cannot overload this operator.
However, there is a class that does more or less than what you are looking for: Data.Bits
with signatures like:
(.&.) :: Bits a => a -> a -> a (.|.) :: Bits a => a -> a -> a complement :: Bits a => a -> a
Data.Bits
commonly used to represent bitwise operations. You can choose to ignore the rest of the operators (return the default) or assign a useful property to it.
Otherwise, you can define similar operators. In this case, one betters first defines the class:
class Logic a where
land :: a -> a -> a
lor :: a -> a -> a
lnot :: a -> a
lnand :: a -> a -> a
lnand x = lnot . land x
lnor :: a -> a -> a
lnor x = lnot . lor x
source to share