zero-0.1.2: src/Data/Zero.hs
-----------------------------------------------------------------------------
-- |
-- Copyright : (C) 2015 Dimitri Sabadie
-- License : BSD3
--
-- Maintainer : Dimitri Sabadie <dimitri.sabadie@gmail.com>
-- Stability : experimental
-- Portability : portable
-----------------------------------------------------------------------------
module Data.Zero (
-- * Semigroups with absorbing element
Zero(..)
-- * Num wrappers
, Product(..)
-- * Boolean wrappers
, Any(..)
, All(..)
-- * Maybe wrappers
, Success(..)
, success
, failure
) where
import Control.Monad.Fix ( MonadFix )
import Data.Monoid ( All(..), Any(..), Product(..) )
import Data.Semigroup ( Semigroup(..) )
-- |'Semigroup' with a 'zero' element. It’s important to understand that the
-- standard 'Semigroup' types – i.e. 'Maybe' and so on – are already biased,
-- because they’re 'Monoid's. That’s why you’ll find a few 'Zero' instances.
--
-- Should satisfies the following laws:
--
-- ==== Annihilation
--
-- @ a '<>' 'zero' = 'zero' '<>' a = 'zero' @
--
-- ==== Associativity
--
-- @ a '<>' b '<>' c = (a '<>' b) '<>' c = a '<>' (b '<>' c) @
class (Semigroup a) => Zero a where
-- |The zero element.
zero :: a
-- |Concat all the elements according to ('<>') and 'zero'.
zconcat :: [a] -> a
default zconcat :: (Semigroup a) => [a] -> a
zconcat [] = zero
zconcat (x:xs) = foldr (<>) x xs
{-# MINIMAL zero #-}
instance Zero () where
zero = ()
instance (Num a) => Zero (Product a) where
zero = Product 0
instance Zero Any where
zero = Any True
instance Zero All where
zero = All False
-- |'Zero' for 'Maybe'.
--
-- Called 'Success' because of the absorbing law:
--
-- @
-- 'Success' ('Just' a) '<>' 'Success' 'Nothing' = 'Nothing'
-- @
newtype Success a = Success { getSuccess :: Maybe a }
deriving (Applicative,Eq,Foldable,Functor,Monad,MonadFix,Ord,Traversable,Read,Show)
instance (Semigroup a) => Semigroup (Success a) where
Success (Just a) <> Success (Just b) = Success . Just $ a <> b
_ <> _ = zero
instance (Semigroup a) => Zero (Success a) where
zero = Success Nothing
-- |A successful value.
success :: a -> Success a
success = Success . Just
-- |A failure.
failure :: Success a
failure = Success Nothing