hasmtlib-2.4.0: src/Language/Hasmtlib/Boolean.hs
{-# LANGUAGE NoImplicitPrelude #-}
module Language.Hasmtlib.Boolean where
import Prelude (Bool(..), (.), id, Eq(..))
import qualified Prelude as P
import Data.Bit
import Data.Coerce
import Data.Bits as Bits
import Data.Foldable hiding (and, or)
import qualified Data.Vector.Unboxed.Sized as V
import GHC.TypeNats
class Boolean b where
-- | Lift a 'Bool'.
bool :: Bool -> b
-- | The true constant.
-- @'true' = 'bool' 'True'@
true :: b
true = bool True
-- | The false constant.
-- @'false' = 'bool' 'False'@
false :: b
false = bool False
-- | Logical conjunction.
(&&) :: b -> b -> b
-- | Logical disjunction (inclusive or).
(||) :: b -> b -> b
-- | Logical implication.
(==>) :: b -> b -> b
x ==> y = not x || y
-- | Logical implication with arrow reversed.
--
-- @
-- forall x y. (x ==> y) === (y <== x)
-- @
(<==) :: b -> b -> b
y <== x = not x || y
-- | Logical equivalence.
(<==>) :: b -> b -> b
x <==> y = (x ==> y) && (y ==> x)
-- | Logical negation.
not :: b -> b
-- | Exclusive-or.
xor :: b -> b -> b
infix 4 `xor`
infixr 4 <==>
infixr 3 &&
infixr 2 ||
infixr 0 ==>
infixl 0 <==
-- | The logical conjunction of several values.
and :: (Foldable t, Boolean b) => t b -> b
and = foldl (&&) true
-- | The logical disjunction of several values.
or :: (Foldable t, Boolean b) => t b -> b
or = foldl (||) false
-- | The negated logical conjunction of several values.
--
-- @'nand' = 'not' . 'and'@
nand :: (Foldable t, Boolean b) => t b -> b
nand = not . and
-- | The negated logical disjunction of several values.
--
-- @'nor' = 'not' . 'or'@
nor :: (Foldable t, Boolean b) => t b -> b
nor = not . or
-- | The logical conjunction of the mapping of a function over several values.
all :: (Foldable t, Boolean b) => (a -> b) -> t a -> b
all p = foldl (\acc b -> acc && p b) true
-- | The logical disjunction of the mapping of a function over several values.
any :: (Foldable t, Boolean b) => (a -> b) -> t a -> b
any p = foldl (\acc b -> acc || p b) false
instance Boolean Bool where
bool = id
true = True
false = False
(&&) = (P.&&)
(||) = (P.||)
not = P.not
xor = (/=)
(<==>) = (==)
instance Boolean Bit where
bool = Bit
(&&) = (.&.)
(||) = (.|.)
not = complement
xor = Bits.xor
x <==> y = bool (x == y)
-- | Defined bitwise
instance KnownNat n => Boolean (V.Vector n Bit) where
bool = V.replicate . coerce
(&&) = V.zipWith (&&)
(||) = V.zipWith (||)
not = V.map not
xor = V.zipWith Bits.xor
x <==> y = bool (x == y)