cond 0.0.2 → 0.1
raw patch · 2 files changed
+110/−37 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Control.Cond: until1M :: Monad m => m Bool -> m a -> m a
- Control.Cond: untilM :: Monad m => m Bool -> m a -> m ()
- Control.Cond: while1M :: Monad m => m Bool -> m a -> m a
- Control.Cond: whileM :: Monad m => m Bool -> m a -> m ()
+ Control.Cond: (<|) :: a -> Maybe a -> a
+ Control.Cond: (?) :: Bool -> (Bool -> a) -> a
+ Control.Cond: (?.) :: Category cat => Bool -> cat a a -> cat a a
+ Control.Cond: (?<>) :: Monoid a => Bool -> a -> a
+ Control.Cond: (|>) :: Bool -> a -> Maybe a
+ Control.Cond: (⊲) :: a -> Maybe a -> a
+ Control.Cond: (⊳) :: Bool -> a -> Maybe a
Files
- cond.cabal +5/−2
- src/Control/Cond.hs +105/−35
cond.cabal view
@@ -1,5 +1,5 @@ Name: cond-Version: 0.0.2+Version: 0.1 Synopsis: Basic conditional and boolean operators with monadic variants. Category: Control, Logic, Monad License: BSD3@@ -11,9 +11,12 @@ Build-Type: Simple Description: A very simple library implementing various conditional operations, as well- as some functions for dealing with conditions and loops in monadic code.+ as some functions for dealing with conditions in monadic code. Feel free to send ideas and suggestions for new conditional operators to the maintainer.++ Monadic looping constructs are not included as part of this package, since the+ monad-loops package has a fairly complete collection of them already. source-repository head type: git
src/Control/Cond.hs view
@@ -2,39 +2,65 @@ module Control.Cond ( -- * Simple conditional operators if', (??), bool- -- * Higher-order conditional- , select -- * Lisp-style conditional operators , cond, condPlus+ -- * Conditional operator on categories+ , (?.)+ -- * Conditional operator on monoids+ , (?<>)+ -- * Conditional operator on functions+ , select+ -- * C-style ternary conditional+ , (?)+ -- *Hoare's conditional choice operator+ -- |The following operators form a ternary conditional of the form+ -- + -- > t <| p |> f+ --+ -- These operators chain with right associative fixity. This allows + -- chaining of conditions, where the result of the expression is + -- the value to the left of the first predicate that succeeds.+ -- + -- For more information see + -- <http://zenzike.com/posts/2011-08-01-the-conditional-choice-operator>+ , (|>), (<|)+ -- **Unicode variants+ -- |Intended to resemble the notation used in Tony Hoare's + -- Unified Theories of Programming.+ , (⊳), (⊲) -- * Lifted conditional and boolean operators , ifM, (<||>), (<&&>), notM, condM, condPlusM- -- * Lifted guard and when , guardM, whenM, unlessM - -- * Monadic looping conditionals- , whileM, untilM, while1M, until1M ) where import Control.Monad+import Control.Category +import Data.Monoid+import Prelude hiding ((.), id) -infixr 1 ??-infixr 2 <||>-infixr 3 <&&>+infixr 0 <|, |>, ⊳, ⊲, ?+infixr 1 ??+infixr 2 <||>+infixr 3 <&&>+infixr 7 ?<>+infixr 9 ?. -- |A simple conditional function. if' :: Bool -> a -> a -> a-if' p a b = if p then a else b+if' p t f = if p then t else f {-# INLINE if' #-} -- |'if'' with the 'Bool' argument at the end (infixr 1). (??) :: a -> a -> Bool -> a-(??) a b p = if' p a b +(??) t f p = if' p t f {-# INLINE (??) #-} --- |A catamorphism for the Bool type. This is analogous to foldr, maybe, and --- either. The first argument is the false case, the second argument is the --- true case, and the last argument is the predicate value.+-- |A catamorphism (aka fold) for the Bool type. This is analogous to +-- '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 :: a -> a -> Bool -> a-bool b a p = if' p a b+bool f t p = if' p t f {-# INLINE bool #-} -- |Lisp-style conditionals. If no conditions match, then a runtime exception@@ -51,10 +77,32 @@ -- |Lisp-style conditionals generalized over 'MonadPlus'. If no conditions -- match, then the result is 'mzero'. This is a safer variant of 'cond'.+--+-- Here's a highly contrived example using 'Data.Maybe.fromMaybe': +--+-- @+-- signum x = fromMaybe 0 . condPlus $ [(x > 0, 1 ) +-- ,(x < 0, -1)]+-- @+--+-- Alternatively, you could use the '<|' operator from Hoare's ternary+-- conditional choice operator, like so:+--+-- @+-- signum x = 0 \<| condPlus [(x > 0, 1 ) +-- ,(x < 0, -1)]+-- @ condPlus :: 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.+(?.) :: Category cat => Bool -> cat a a -> cat a a+p ?. c = if' p c id+{-# INLINE (?.) #-}+ -- |Composes a predicate function and 2 functions into a single -- function. The first function is called when the predicate yields True, the -- second when the predicate yields False.@@ -62,26 +110,26 @@ -- Note that after importing "Control.Monad.Instances", 'select' becomes a -- special case of 'ifM'. select :: (a -> Bool) -> (a -> b) -> (a -> b) -> (a -> b)-select p a b x = if' (p x) (a x) (b x)+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 :: Monad m => m Bool -> m a -> m a -> m a -ifM p a b = p >>= bool b a+ifM p t f = p >>= bool f t {-# INLINE ifM #-} -- |Lifted boolean or. Unlike 'liftM2' ('||'), This function is short-circuiting -- in the monad. Fixity is the same as '||' (infixr 2). (<||>) :: Monad m => m Bool -> m Bool -> m Bool-(<||>) a b = ifM a (return True) b+(<||>) t f = ifM t (return True) f {-# INLINE (<||>) #-} -- |Lifted boolean and. Unlike 'liftM2' ('&&'), this function is -- short-circuiting in the monad. Fixity is the same as '&&' (infxr 3). (<&&>) :: Monad m => m Bool -> m Bool -> m Bool-(<&&>) a b = ifM a b (return False)+(<&&>) t f = ifM t f (return False) {-# INLINE (<&&>) #-} -- |Lifted boolean negation.@@ -116,23 +164,45 @@ guardM = (guard =<<) {-# INLINE guardM #-} --- |A monadic while loop.-whileM :: Monad m => m Bool -> m a -> m ()-whileM p m = whenM p (m >> whileM p m) +-- |Conditional monoid operator. If the predicate is 'False', the second+-- argument is replaced with 'mempty'. The fixity of this operator is one+-- level higher than 'Control.Monoid.<>'. +--+-- It can also be used to chain multiple predicates together, like this: +--+-- > even (length ls) ?<> not (null ls) ?<> ls+(?<>) :: Monoid a => Bool -> a -> a+p ?<> m = if' p m mempty+{-# INLINE (?<>) #-}+ --- |A monadic while loop with a negated conditional.-untilM :: Monad m => m Bool -> m a -> m ()-untilM p = whileM (notM p)-{-# INLINE untilM #-}+-- |An operator that allows you to write C-style ternary conditionals of+-- the form:+--+-- > p ? t ?? f+--+-- Note that parentheses are required in order to chain sequences of+-- conditionals together. This is probably a good thing.+(?) :: Bool -> (Bool -> a) -> a+p ? f = f p --- |A monadic do-while loop. The monadic action is guaranteed to be executed --- once. Because of this, we can also return the result of the last execution --- of the loop.-while1M :: Monad m => m Bool -> m a -> m a-while1M p m = do a <- m- ifM p (while1M p m) (return a)+-- |right bracket of the conditional choice operator. If the predicate+-- is 'False', returns 'Nothing', otherwise it returns 'Just' the right-hand+-- argument.+(|>) :: Bool -> a -> Maybe a+True |> _ = Nothing+False |> f = Just f --- |A negated do-while loop.-until1M :: Monad m => m Bool -> m a -> m a-until1M p = while1M (notM p)-{-# INLINE until1M #-}+-- |left bracket of the conditional choice operator. This is equivalent to+-- 'Data.Maybe.fromMaybe'+(<|) :: a -> Maybe a -> a+t <| Nothing = t+_ <| Just f = f++-- |Unicode rebinding of '|>'. +(⊲) :: a -> Maybe a -> a+(⊲) = (<|)++-- |Unicode rebinding of '<|'.+(⊳) :: Bool -> a -> Maybe a+(⊳) = (|>)