cond 0.3 → 0.4
raw patch · 4 files changed
+91/−45 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Control.Conditional: condDefault :: ToBool bool => a -> [(bool, a)] -> a
+ Data.Algebra.Boolean: Bitwise :: a -> Bitwise a
+ Data.Algebra.Boolean: getBits :: Bitwise a -> a
+ Data.Algebra.Boolean: instance Bits a => Bits (Bitwise a)
+ Data.Algebra.Boolean: instance Bits a => Boolean (Bitwise a)
+ Data.Algebra.Boolean: instance Bounded a => Bounded (Bitwise a)
+ Data.Algebra.Boolean: instance Data a => Data (Bitwise a)
+ Data.Algebra.Boolean: instance Enum a => Enum (Bitwise a)
+ Data.Algebra.Boolean: instance Eq a => Eq (Bitwise a)
+ Data.Algebra.Boolean: instance Integral a => Integral (Bitwise a)
+ Data.Algebra.Boolean: instance Ix a => Ix (Bitwise a)
+ Data.Algebra.Boolean: instance Num a => Num (Bitwise a)
+ Data.Algebra.Boolean: instance Ord a => Ord (Bitwise a)
+ Data.Algebra.Boolean: instance PrintfArg a => PrintfArg (Bitwise a)
+ Data.Algebra.Boolean: instance Read a => Read (Bitwise a)
+ Data.Algebra.Boolean: instance Real a => Real (Bitwise a)
+ Data.Algebra.Boolean: instance Show a => Show (Bitwise a)
+ Data.Algebra.Boolean: instance Storable a => Storable (Bitwise a)
+ Data.Algebra.Boolean: instance Typeable1 Bitwise
+ Data.Algebra.Boolean: newtype Bitwise a
- Control.Conditional: (<&&>) :: (ToBool b, Boolean b, Monad m) => m b -> m b -> m b
+ Control.Conditional: (<&&>) :: (ToBool bool, Boolean bool, Monad m) => m bool -> m bool -> m bool
- Control.Conditional: (<||>) :: (ToBool b, Boolean b, Monad m) => m b -> m b -> m b
+ Control.Conditional: (<||>) :: (ToBool bool, Boolean bool, Monad m) => m bool -> m bool -> m bool
- Control.Conditional: (?.) :: (ToBool b, Category cat) => b -> cat a a -> cat a a
+ Control.Conditional: (?.) :: (ToBool bool, Category cat) => bool -> cat a a -> cat a a
- Control.Conditional: (?<>) :: (ToBool b, Monoid a) => b -> a -> a
+ Control.Conditional: (?<>) :: (ToBool bool, Monoid a) => bool -> a -> a
- Control.Conditional: (??) :: ToBool b => a -> a -> b -> a
+ Control.Conditional: (??) :: ToBool bool => a -> a -> bool -> a
- Control.Conditional: (|>) :: ToBool b => b -> a -> Maybe a
+ Control.Conditional: (|>) :: ToBool bool => bool -> a -> Maybe a
- Control.Conditional: (|>>) :: (ToBool b, Monad m) => m b -> m a -> m (Maybe a)
+ Control.Conditional: (|>>) :: (ToBool bool, Monad m) => m bool -> m a -> m (Maybe a)
- Control.Conditional: (⊳) :: ToBool b => b -> a -> Maybe a
+ Control.Conditional: (⊳) :: ToBool bool => bool -> a -> Maybe a
- Control.Conditional: bool :: ToBool b => a -> a -> b -> a
+ Control.Conditional: bool :: ToBool bool => a -> a -> bool -> a
- Control.Conditional: class ToBool b
+ Control.Conditional: class ToBool bool
- Control.Conditional: cond :: ToBool b => [(b, a)] -> a
+ Control.Conditional: cond :: ToBool bool => [(bool, a)] -> a
- Control.Conditional: condM :: (ToBool b, Monad m) => [(m b, m a)] -> m a
+ Control.Conditional: condM :: (ToBool bool, Monad m) => [(m bool, m a)] -> m a
- Control.Conditional: condPlus :: (ToBool b, MonadPlus m) => [(b, a)] -> m a
+ Control.Conditional: condPlus :: (ToBool bool, MonadPlus m) => [(bool, a)] -> m a
- Control.Conditional: condPlusM :: (ToBool b, MonadPlus m) => [(m b, m a)] -> m a
+ Control.Conditional: condPlusM :: (ToBool bool, MonadPlus m) => [(m bool, m a)] -> m a
- Control.Conditional: guard :: (ToBool b, MonadPlus m) => b -> m ()
+ Control.Conditional: guard :: (ToBool bool, MonadPlus m) => bool -> m ()
- Control.Conditional: guardM :: (ToBool b, MonadPlus m) => m b -> m ()
+ Control.Conditional: guardM :: (ToBool bool, MonadPlus m) => m bool -> m ()
- Control.Conditional: if' :: ToBool b => b -> a -> a -> a
+ Control.Conditional: if' :: ToBool bool => bool -> a -> a -> a
- Control.Conditional: ifM :: (ToBool b, Monad m) => m b -> m a -> m a -> m a
+ Control.Conditional: ifM :: (ToBool bool, Monad m) => m bool -> m a -> m a -> m a
- Control.Conditional: notM :: (Boolean b, Monad m) => m b -> m b
+ Control.Conditional: notM :: (Boolean bool, Monad m) => m bool -> m bool
- Control.Conditional: otherwiseM :: (Boolean b, Monad m) => m b
+ Control.Conditional: otherwiseM :: (Boolean bool, Monad m) => m bool
- Control.Conditional: select :: ToBool p => (a -> p) -> (a -> b) -> (a -> b) -> (a -> b)
+ Control.Conditional: select :: ToBool bool => (a -> bool) -> (a -> b) -> (a -> b) -> (a -> b)
- Control.Conditional: selectM :: (ToBool p, Monad m) => (a -> m p) -> (a -> m b) -> (a -> m b) -> (a -> m b)
+ Control.Conditional: selectM :: (ToBool bool, Monad m) => (a -> m bool) -> (a -> m b) -> (a -> m b) -> (a -> m b)
- Control.Conditional: toBool :: ToBool b => b -> Bool
+ Control.Conditional: toBool :: ToBool bool => bool -> Bool
- Control.Conditional: unless :: (Boolean b, ToBool b, MonadPlus m) => b -> m () -> m ()
+ Control.Conditional: unless :: (Boolean bool, ToBool bool, MonadPlus m) => bool -> m () -> m ()
- Control.Conditional: unlessM :: (ToBool b, Boolean b, Monad m) => m b -> m () -> m ()
+ Control.Conditional: unlessM :: (ToBool bool, Boolean bool, Monad m) => m bool -> m () -> m ()
- Control.Conditional: when :: (ToBool b, MonadPlus m) => b -> m () -> m ()
+ Control.Conditional: when :: (ToBool bool, MonadPlus m) => bool -> m () -> m ()
- Control.Conditional: whenM :: (ToBool b, Monad m) => m b -> m () -> m ()
+ Control.Conditional: whenM :: (ToBool bool, Monad m) => m bool -> m () -> m ()
- Control.Conditional: xorM :: (Boolean b, Monad m) => m b -> m b -> m b
+ Control.Conditional: xorM :: (Boolean bool, Monad m) => m bool -> m bool -> m bool
- Data.Algebra.Boolean: class Boolean b where not = (<--> false) x && y = not (x || y) x || y = not (x && y) x xor y = (x || y) && (not (x && y)) x --> y = not x || y x <--> y = (x && y) || not (x || y)
+ Data.Algebra.Boolean: class Boolean b where true = not false false = not true not = (<--> false) x && y = not (x || y) x || y = not (x && y) x xor y = (x || y) && (not (x && y)) x --> y = not x || y x <--> y = (x && y) || not (x || y)
Files
- README.md +10/−0
- cond.cabal +3/−1
- src/Control/Conditional.hs +37/−30
- src/Data/Algebra/Boolean.hs +41/−14
+ README.md view
@@ -0,0 +1,10 @@+# Description++A library of boolean operations, lifted in a typeclass for boolean values.+Also includes:++* Lifted monadic variants of those operations.+* Hoare's conditional choice operator.+* A typeclass for boolean algebras.++See annotated documentation in code for information about individual entities.
cond.cabal view
@@ -1,5 +1,5 @@ Name: cond-Version: 0.3+Version: 0.4 Synopsis: Basic conditional and boolean operators with monadic variants. Category: Control, Logic, Monad License: BSD3@@ -23,6 +23,8 @@ . Monadic looping constructs are not included as part of this package, since the monad-loops package has a fairly complete collection of them already.+Extra-source-files:+ README.md source-repository head type: git
src/Control/Conditional.hs view
@@ -7,7 +7,7 @@ , if', (??), bool , ifM, (<||>), (<&&>), notM, xorM -- * Lisp-style conditional operators - , cond, condPlus, condM, condPlusM, otherwiseM+ , cond, condDefault, condPlus, condM, condPlusM, otherwiseM -- * Conditional operator on categories , (?.) -- * Conditional operator on monoids@@ -62,8 +62,8 @@ -- > p || q = if toBool p then true else q -- -- > p && q = if toBool p then q else false-class ToBool b where- toBool :: b -> Bool+class ToBool bool where+ toBool :: bool -> Bool instance ToBool Bool where toBool = id instance ToBool Any where toBool = getAny@@ -71,11 +71,12 @@ instance ToBool (Dual Bool) where toBool = getDual -- |A simple conditional operator-if' :: ToBool b => b -> a -> a -> a+if' :: ToBool bool => bool -> a -> a -> a if' p t f = if toBool p then t else f+{-# INLINE if' #-} -- |'if'' with the 'Bool' argument at the end (infixr 1).-(??) :: ToBool b => a -> a -> b -> a+(??) :: ToBool bool => a -> a -> bool -> a (??) t f p = if' p t f {-# INLINE (??) #-} @@ -83,7 +84,7 @@ -- 'foldr', 'Data.Maybe.maybe', and 'Data.Either.either'. The first argument is -- the false case, the second argument is the true case, and the last argument -- is the predicate value.-bool :: (ToBool b) => a -> a -> b -> a+bool :: (ToBool bool) => a -> a -> bool -> a bool f t p = if' p t f {-# INLINE bool #-} @@ -95,10 +96,16 @@ -- ,(x < 0 , -1) -- ,(otherwise , 0 )] -- @-cond :: ToBool b => [(b, a)] -> a+cond :: ToBool bool => [(bool, a)] -> a cond [] = error "cond: no matching conditions" cond ((p,v):ls) = if' p v (cond ls) +-- | Analogous to the 'cond' function with a default value supplied,+-- which will be used when no condition in the list is matched.+condDefault :: ToBool bool => a -> [(bool, a)] -> a+condDefault = (. condPlus) . (<|)+{-# INLINE condDefault #-}+ -- |Lisp-style conditionals generalized over 'MonadPlus'. If no conditions -- match, then the result is 'mzero'. This is a safer variant of 'cond'. --@@ -116,14 +123,14 @@ -- signum x = 0 \<| condPlus [(x > 0, 1 ) -- ,(x < 0, -1)] -- @-condPlus :: (ToBool b, MonadPlus m) => [(b, a)] -> m a+condPlus :: (ToBool bool, MonadPlus m) => [(bool, a)] -> m a condPlus [] = mzero condPlus ((p,v):ls) = if' p (return v) (condPlus ls) -- |Conditional composition. If the predicate is False, 'id' is returned -- instead of the second argument. This function, for example, can be used to -- conditionally add functions to a composition chain.-(?.) :: (ToBool b, Category cat) => b -> cat a a -> cat a a+(?.) :: (ToBool bool, Category cat) => bool -> cat a a -> cat a a p ?. c = if' p c id {-# INLINE (?.) #-} @@ -133,87 +140,87 @@ -- -- Note that after importing "Control.Monad.Instances", 'select' becomes a -- special case of 'ifM'.-select :: ToBool p => (a -> p) -> (a -> b) -> (a -> b) -> (a -> b)+select :: ToBool bool => (a -> bool) -> (a -> b) -> (a -> b) -> (a -> b) select p t f x = if' (p x) (t x) (f x) {-# INLINE select #-} -- |'if'' lifted to 'Monad'. Unlike 'liftM3' 'if'', this is -- short-circuiting in the monad, such that only the predicate action and one of -- the remaining argument actions are executed.-ifM :: (ToBool b, Monad m) => m b -> m a -> m a -> m a +ifM :: (ToBool bool, Monad m) => m bool -> m a -> m a -> m a ifM p t f = p >>= bool f t {-# INLINE ifM #-} -- |Lifted inclusive disjunction. Unlike 'liftM2' ('||'), This function is -- short-circuiting in the monad. Fixity is the same as '||' (infixr 2).-(<||>) :: (ToBool b, Boolean b, Monad m) => m b -> m b -> m b+(<||>) :: (ToBool bool, Boolean bool, Monad m) => m bool -> m bool -> m bool (<||>) t f = ifM t (return true) f {-# INLINE (<||>) #-} -- |Lifted conjunction. Unlike 'liftM2' ('&&'), this function is -- short-circuiting in the monad. Fixity is the same as '&&' (infxr 3).-(<&&>) :: (ToBool b, Boolean b, Monad m) => m b -> m b -> m b+(<&&>) :: (ToBool bool, Boolean bool, Monad m) => m bool -> m bool -> m bool (<&&>) t f = ifM t f (return false) {-# INLINE (<&&>) #-} -- |Lifted boolean negation.-notM :: (Boolean b, Monad m) => m b -> m b+notM :: (Boolean bool, Monad m) => m bool -> m bool notM = liftM not {-# INLINE notM #-} -- |Lifted boolean exclusive disjunction.-xorM :: (Boolean b, Monad m) => m b -> m b -> m b+xorM :: (Boolean bool, Monad m) => m bool -> m bool -> m bool xorM = liftM2 xor -- |'cond' lifted to 'Monad'. If no conditions match, a runtime exception -- is thrown.-condM :: (ToBool b, Monad m) => [(m b, m a)] -> m a +condM :: (ToBool bool, Monad m) => [(m bool, m a)] -> m a condM [] = error "condM: no matching conditions" condM ((p, v):ls) = ifM p v (condM ls) -- |'condPlus' lifted to 'Monad'. If no conditions match, then 'mzero' -- is returned.-condPlusM :: (ToBool b, MonadPlus m) => [(m b, m a)] -> m a+condPlusM :: (ToBool bool, MonadPlus m) => [(m bool, m a)] -> m a condPlusM [] = mzero condPlusM ((p, v):ls) = ifM p v (condPlusM ls) -- |A synonym for 'return' 'true'.-otherwiseM :: (Boolean b, Monad m) => m b+otherwiseM :: (Boolean bool, Monad m) => m bool otherwiseM = return true -- |Generalization of 'Control.Monad.guard'-guard :: (ToBool b, MonadPlus m) => b -> m ()+guard :: (ToBool bool, MonadPlus m) => bool -> m () guard p = if' p (return ()) mzero {-# INLINE guard #-} -- |Generalization of 'Control.Monad.when'-when :: (ToBool b, MonadPlus m) => b -> m () -> m ()+when :: (ToBool bool, MonadPlus m) => bool -> m () -> m () when p m = if' p m (return ()) {-# INLINE when #-} -- |Generalization of 'Control.Monad.unless'-unless :: (Boolean b, ToBool b, MonadPlus m) => b -> m() -> m()+unless :: (Boolean bool, ToBool bool, MonadPlus m) => bool -> m() -> m() unless p m = if' (not p) m (return ()) {-# INLINE unless #-} -- |A variant of 'when' with a monadic predicate.-whenM :: (ToBool b, Monad m) => m b -> m () -> m ()+whenM :: (ToBool bool, Monad m) => m bool -> m () -> m () whenM p m = ifM p m (return ()) {-# INLINE whenM #-} -- |A variant of 'unless' with a monadic predicate.-unlessM :: (ToBool b, Boolean b, Monad m) => m b -> m () -> m ()+unlessM :: (ToBool bool, Boolean bool, Monad m) => m bool -> m () -> m () unlessM p m = ifM (notM p) m (return ()) {-# INLINE unlessM #-} -- |A variant of 'guard' with a monadic predicate.-guardM :: (ToBool b, MonadPlus m) => m b -> m ()+guardM :: (ToBool bool, MonadPlus m) => m bool -> m () guardM = (guard =<<) {-# INLINE guardM #-} -- |'select' lifted to 'Monad'.-selectM :: (ToBool p, Monad m) => - (a -> m p) -> (a -> m b) -> (a -> m b) -> (a -> m b)+selectM :: (ToBool bool, Monad m) => + (a -> m bool) -> (a -> m b) -> (a -> m b) -> (a -> m b) selectM p t f x = ifM (p x) (t x) (f x) {-# INLINE selectM #-} @@ -224,7 +231,7 @@ -- It can also be used to chain multiple predicates together, like this: -- -- > even (length ls) ?<> not (null ls) ?<> ls-(?<>) :: (ToBool b, Monoid a) => b -> a -> a+(?<>) :: (ToBool bool, Monoid a) => bool -> a -> a p ?<> m = if' p m mempty {-# INLINE (?<>) #-} @@ -243,7 +250,7 @@ -- |Right bracket of the conditional choice operator. If the predicate -- is 'False', returns 'Nothing', otherwise it returns 'Just' the right-hand -- argument.-(|>) :: ToBool b => b -> a -> Maybe a+(|>) :: ToBool bool => bool -> a -> Maybe a p |> v = if' p Nothing (Just v) {-# INLINE (|>) #-} @@ -255,7 +262,7 @@ {-# INLINE (<|) #-} -- |A monadic variant of '|>'.-(|>>) :: (ToBool b, Monad m) => m b -> m a -> m (Maybe a)+(|>>) :: (ToBool bool, Monad m) => m bool -> m a -> m (Maybe a) p |>> v = ifM p (return Nothing) (liftM Just v) {-# INLINE (|>>) #-} @@ -269,5 +276,5 @@ (⊲) = (<|) -- |Unicode rebinding of '|>'.-(⊳) :: ToBool b => b -> a -> Maybe a+(⊳) :: ToBool bool => bool -> a -> Maybe a (⊳) = (|>)
src/Data/Algebra/Boolean.hs view
@@ -1,37 +1,50 @@-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, + DeriveDataTypeable + #-} module Data.Algebra.Boolean - ( Boolean(..), fromBool+ ( Boolean(..), fromBool, Bitwise(..) ) where import Data.Monoid (Any(..), All(..), Dual(..), Endo(..))+import Data.Bits (Bits, complement, (.|.), (.&.))+import qualified Data.Bits as Bits+import Data.Function (on)+import Data.Typeable+import Data.Data+import Data.Ix+import Foreign.Storable+import Text.Printf import Prelude hiding ((&&), (||), not) import qualified Prelude as P-infixr 0 -->++infixr 1 <-->, `xor`, --> infixr 2 || infixr 3 && --- |A class for boolean algebras. Instances of this class should obey--- all the axioms of boolean algebra.+-- |A class for boolean algebras. Instances of this class are expected to obey+-- all the laws of boolean algebra. ----- Minimal complete definition: 'true', 'false', 'not' or '<-->', '||' or '&&'. +-- Minimal complete definition: 'true' or 'false', 'not' or '<-->', '||' or '&&'. class Boolean b where- -- |Truth value.+ -- |Truth value, defined as the top of the bounded lattice true :: b- -- |False value.+ -- |False value, defined as the bottom of the bounded lattice. false :: b -- |Logical negation. not :: b -> b- -- |Logical conjunction.+ -- |Logical conjunction. (infxr 3) (&&) :: b -> b -> b- -- |Logical inclusive disjunction.+ -- |Logical inclusive disjunction. (infixr 2) (||) :: b -> b -> b- -- |Logical exclusive disjunction.+ -- |Logical exclusive disjunction. (infixr 1) xor :: b -> b -> b- -- |Logical implication+ -- |Logical implication. (infixr 1) (-->) :: b -> b -> b- -- |Logical biconditional+ -- |Logical biconditional. (infixr 1) (<-->) :: b -> b -> b -- Default implementations+ true = not false+ false = not true not = (<--> false) x && y = not (x || y) x || y = not (x && y)@@ -55,7 +68,6 @@ False --> _ = True (<-->) = (==) - instance Boolean Any where true = Any True false = Any False@@ -95,3 +107,18 @@ (Endo p) `xor` (Endo q) = Endo (\a -> p a `xor` q a) (Endo p) --> (Endo q) = Endo (\a -> p a --> q a) (Endo p) <--> (Endo q) = Endo (\a -> p a <--> q a)+ ++newtype Bitwise a = Bitwise {getBits :: a} + deriving (Num, Bits, Eq, Ord, Bounded, Enum, Show, Read, Real,+ Integral, Typeable, Data, Ix, Storable, PrintfArg)++instance Bits a => Boolean (Bitwise a) where+ true = not false + false = Bitwise 0 + not = Bitwise . complement . getBits+ (&&) = (Bitwise .) . (.&.) `on` getBits+ (||) = (Bitwise .) . (.|.) `on` getBits+ xor = (Bitwise .) . (Bits.xor `on` getBits)+ (<-->) = xor `on` not+