bool-extras-0.4.0: src/Data/Bool/Extras.hs
{-# LANGUAGE CPP #-}
-- | This module provides some convenient functions for dealing with Booleans.
--
-- The most important one being 'bool', a function that can be used in place of
-- the build-in @if then else@-syntax.
module Data.Bool.Extras
(
-- * Main function
bool
-- * Other functions
, mwhen
, mwhenM
, whenA
, whenC
, whenM
-- * Morphisms
, BoolAlgebra
, cata
, ana
) where
import Control.Arrow
import Control.Category (Category)
import qualified Control.Category as Cat
import Control.Monad
import Data.Bool
import Data.Monoid
#if !MIN_VERSION_base(4,7,0)
-- | Defines the fold over a boolean value.
--
-- Returns its first argument when applied to `False',
-- returns its second argument when applied to `True'.
--
-- Comparable to the `maybe' or `either' functions for their respective data
-- types.
{-# INLINE bool #-}
bool :: a -> a -> Bool -> a
bool x _ False = x
bool _ y True = y
-- Expressed in terms of `cata':
-- bool = curry cata
#endif
-- | Boolean operation for monoids.
--
-- Returns its first argument when applied to `True',
-- returns `mempty' when applied to `False'.
mwhen :: (Monoid a) => a -> Bool -> a
mwhen = bool mempty
-- | Boolean operation for monads, with a monoid default.
--
-- Return its first argument when applied to `True',
-- returns `return mempty' when applied to `False'.
mwhenM :: (Monad m, Monoid a) => m a -> Bool -> m a
mwhenM = bool (return mempty)
-- | Boolean operation for arrows.
--
-- Returns its first argument when applied to `True',
-- returns `returnA' when applied to `False'.
whenA :: (Arrow a) => a b b -> Bool -> a b b
whenA = bool returnA
-- | Boolean operation for categories.
--
-- Returns its first argument when applied to `True',
-- returns @Control.Category.@`Cat.id' when applied to `False'.
whenC :: (Category cat) => cat a a -> Bool -> cat a a
whenC = bool Cat.id
-- | Boolean operation for monads.
--
-- Returns its first argument when applied to `True',
-- returns `return' when applied to `False'.
--
-- @Control.Monad.@`when' can be expressed in terms of `whenM', like so:
--
-- > when :: Monad m => Bool -> m () -> m ()
-- > when b m = (const m `whenM` b) ()
whenM :: (Monad m) => (a -> m a) -> Bool -> (a -> m a)
whenM = bool return
-- Alternative implementation using Kleisli arrows:
-- whenM m = runKleisli . whenC (Kleisli m)
{-
-- Functions that are also possible, but we haven't found an explicit need for
whenP :: (MonadPlus m) => a -> Bool -> m a
whenP = bool mzero . return
(<?>) :: (Applicative f) => (a -> f a) -> Bool -> (a -> f a)
(<?>) = bool pure
-}
-- | Algebra for Bool data type.
--
-- The first field of the pair represents the `False' value,
-- the second field represents the `True' value.
type BoolAlgebra r = (r, r)
-- | Catamorphism for booleans.
cata :: BoolAlgebra r -> Bool -> r
cata (x, _) False = x
cata (_, y) True = y
-- | Anamorphism for booleans.
ana :: (b -> Bool) -> b -> Bool
ana f b = f b