简体   繁体   中英

Is it possible to overload logical operators (&& e.g.) in Haskell?

I'm working with many-valued logic and trying to overload basic logic functions.

I haven't problem with overloading Num and Eq operators, but I don't know how to overload &&, || and not .

Is it possible? Thanks for answers!

Haskell doesn't really have overloading (= ad-hoc-polymorphism ) at all. + , * etc. are not functions but class methods : “overloading” them is more like defining concrete descendants of an OO interface / purely-abstract class than overloading functions in, say, C++.

The logical operators OTOH are just ordinary functions, which are defined in the Prelude once and for all.

However, in Haskell, infix operators are mostly treated just as a special kind of function name, they're not part of the actual syntax definition. Nothing prevents you from defining new, different operators with the same purpose, eg

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's enough if the new names are disambiguated by module qualifiers:

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.||)

There is no such thing as overriding in Haskell in the monkeypatching sense.

There's also no way to hook an extension into something that wasn't built to be extended.

You can simply shadow the definition of eg && but this would 1) not affect the semantics of && in other modules and 2) would be confusing.

So I would use something as simple as:

-- 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
  ...

No, it's not possible. The type of && is Bool -> Bool -> Bool , and Haskell doesn't allow ad-hoc overloading. You can shadow the declaration, but then you can't use the operator for both booleans and your mvl values in the same module without qualification.

I recommend you define similar-looking operators such as &&? for your mvls.

You can't override them, but you can define your own.

infixr 3 <&&> <||>

<&&> :: ??? -> ??? -> ???
<&&> ...

(&&) is defined as

(&&) :: Bool -> Bool -> Bool

So unless you don't load the Prelude , or load it qualified, you cannot overload that operator.

There is however a typeclass that does more or less 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 is normally used to represent bitwise operations. You could decide to ignore the remaining operators (return some default value) or assign a useful property to it.

Otherwise you can define similar operators. In that case one betters defines a typeclass first:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM