packages feed

either 3.4.1 → 3.4.2

raw patch · 3 files changed

+311/−2 lines, 3 files

Files

CHANGELOG.markdown view
@@ -1,3 +1,7 @@+3.4.2+-----+* Added 'Data.Either.Combinators'.+ 3.4.1 ----- * Trustworthy despite UndecidableInstances
either.cabal view
@@ -1,6 +1,6 @@ name:          either category:      Control, Monads-version:       3.4.1+version:       3.4.2 license:       BSD3 cabal-version: >= 1.6 license-file:  LICENSE@@ -35,6 +35,7 @@     transformers  >= 0.2     && < 0.4    extensions: CPP-  exposed-modules: Control.Monad.Trans.Either+  exposed-modules: Control.Monad.Trans.Either,+                   Data.Either.Combinators   ghc-options: -Wall   hs-source-dirs: src
+ src/Data/Either/Combinators.hs view
@@ -0,0 +1,304 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Data.Either.Combinators+-- Copyright   :  (c) Gregory Crosswhite, Chris Done, Edward Kmett+-- License     :  BSD-style+--+-- Maintainer  :  ekmett@gmail.com+-- Stability   :  provisional+-- Portability :  portable+--+-- Functions for probing and unwrapping values inside of 'Either'.+--+-- Most of these combinators are provided for pedagogical purposes and exist+-- in more general forms in other libraries. To that end alternative definitions+-- are supplied below.+--+-----------------------------------------------------------------------------++module Data.Either.Combinators+  ( isLeft+  , isRight+  , fromLeft+  , fromRight+  , fromLeft'+  , fromRight'+  , mapBoth+  , mapLeft+  , mapRight+  , whenLeft+  , whenRight+  , unlessLeft+  , unlessRight+  , leftToMaybe+  , rightToMaybe+  ) where++import Control.Applicative++-- ---------------------------------------------------------------------------+-- Functions over Either++-- |The 'isLeft' function returns 'True' iff its argument is of the form @Left _@.+--+-- Using @Control.Lens@:+--+-- @+-- 'isLeft' ≡ has _Left+-- @+--+-- >>> isLeft (Left 12)+-- True+--+-- >>> isLeft (Right 12)+-- False+isLeft :: Either a b -> Bool+isLeft (Left _) = True+isLeft _        = False++-- |The 'isRight' function returns 'True' iff its argument is of the form @Right _@.+--+-- Using @Control.Lens@:+--+-- @+-- 'isRight' ≡ has _Right+-- @+--+-- >>> isRight (Left 12)+-- False+--+-- >>> isRight (Right 12)+-- True+isRight :: Either a b -> Bool+isRight (Right _) = True+isRight _         = False++-- | Extracts the element out of a 'Left' and+-- throws an error if its argument take the form  @'Right' _@.+--+-- Using @Control.Lens@:+--+-- @+-- 'fromLeft'' x ≡ x^?!_Left+-- @+--+-- >>> fromLeft' (Left 12)+-- 12+fromLeft' :: Either a b -> a+fromLeft' (Right _) = error "Data.Either.Combinators.fromLeft: Argument takes form 'Right _'" -- yuck+fromLeft' (Left x)  = x++-- | Extracts the element out of a 'Right' and+-- throws an error if its argument take the form  @'Left' _@.+--+-- Using @Control.Lens@:+--+-- @+-- 'fromRight'' x ≡ x^?!_Right+-- @+--+-- >>> fromRight' (Right 12)+-- 12+fromRight' :: Either a b -> b+fromRight' (Left _)  = error "Data.Either.Combinators.fromRight: Argument takes form 'Left _'" -- yuck+fromRight' (Right x) = x++-- | The 'mapBoth' function takes two functions and applies the first if iff the value+-- takes the form @'Left' _@ and the second if the value takes the form @'Right' _@.+--+-- Using @Data.Bifunctor@:+--+-- @+-- 'mapBoth' = bimap+-- @+--+-- Using @Control.Arrow@:+--+-- @+-- 'mapBoth' = ('Control.Arrow.+++')+-- @+--+-- >>> mapBoth (*2) (*3) (Left 4)+-- Left 8+--+-- >>> mapBoth (*2) (*3) (Right 4)+-- Right 12+mapBoth :: (a -> c) -> (b -> d) -> Either a b -> Either c d+mapBoth f _ (Left x)  = Left (f x)+mapBoth _ f (Right x) = Right (f x)++-- | The 'mapLeft' function takes a function and applies it to an Either value+-- iff the value takes the form 'Left _'.+--+-- Using @Data.Bifunctor@:+--+-- @+-- 'mapLeft' = first+-- @+--+-- Using @Control.Arrow@:+--+-- @+-- 'mapLeft' = ('Control.Arrow.left')+-- @+--+-- Using @Control.Lens@:+--+-- @+-- 'mapLeft' = over _Left+-- @+--+-- >>> mapLeft (*2) (Left 4)+-- Left 8+--+-- >>> mapLeft (*2) (Right "hello")+-- Right "hello"+mapLeft :: (a -> c) -> Either a b -> Either c b+mapLeft f = mapBoth f id++-- | The 'mapLeft' function takes a function and applies it to an Either value+-- iff the value takes the form 'Left _'.+--+-- Using @Data.Bifunctor@:+--+-- @+-- 'mapRight' = first+-- @+--+-- Using @Control.Arrow@:+--+-- @+-- 'mapRight' = ('Control.Arrow.right')+-- @+--+-- Using @Control.Lens@:+--+-- @+-- 'mapRight' = 'over' '_Right'+-- @+--+-- >>> mapRight (*2) (Left "hello")+-- Left "hello"+--+-- >>> mapRight (*2) (Right 4)+-- Right 8+mapRight :: (b -> c) -> Either a b -> Either a c+mapRight = mapBoth id++-- | The 'whenLeft' function takes an 'Either' value and a function which returns a monad.+-- The monad is only executed when the given argument takes the form @Left _@, otherwise+-- it does nothing.+--+-- Using @Control.Lens@:+--+-- @+-- 'whenLeft' ≡ forOf_ _Left+-- @+--+-- >>> whenLeft (Left 12) print+-- 12+whenLeft :: Applicative m => Either a b -> (a -> m ()) -> m ()+whenLeft (Left x) f = f x+whenLeft _        _ = pure ()++-- | The 'whenLeft' function takes an 'Either' value and a function which returns a monad.+-- The monad is only executed when the given argument takes the form @Right _@, otherwise+-- it does nothing.+--+-- Using @Data.Foldable@:+--+-- @+-- 'whenRight' ≡ 'forM_'+-- @+--+-- Using @Control.Lens@:+--+-- @+-- 'whenRight' ≡ forOf_ _Right+-- @+--+-- >>> whenRight (Right 12) print+-- 12+whenRight :: Applicative m => Either a b -> (b -> m ()) -> m ()+whenRight (Right x) f = f x+whenRight _         _ = pure ()++-- | A synonym of 'whenRight'.+unlessLeft :: Applicative m => Either a b -> (b -> m ()) -> m ()+unlessLeft = whenRight++-- | A synonym of 'whenLeft'.+unlessRight :: Applicative m => Either a b -> (a -> m ()) -> m ()+unlessRight = whenLeft++-- | Extract the left value or a default.+--+-- @+-- 'fromLeft' ≡ 'either' 'id'+-- @+--+-- >>> fromLeft "hello" (Right 42)+-- "hello"+--+-- >>> fromLeft "hello" (Left "world")+-- "world"+fromLeft :: a -> Either a b -> a+fromLeft _ (Left x) = x+fromLeft x _ = x++-- | Extract the right value or a default.+--+-- @+-- 'fromRight' b ≡ 'either' b 'id'+-- @+--+-- >>> fromRight "hello" (Right "world")+-- "world"+--+-- >>> fromRight "hello" (Left 42)+-- "hello"+fromRight :: b -> Either a b -> b+fromRight _ (Right x) = x+fromRight x _ = x++-- | Maybe get the 'Left' side of an 'Either'.+--+-- @+-- 'leftToMaybe' ≡ 'either' 'Just' ('const' 'Nothing')+-- @+--+-- Using @Control.Lens@:+--+-- @+-- 'leftToMaybe' ≡ preview _Left+-- 'leftToMaybe' x ≡ x^?_Left+-- @+--+-- >>> leftToMaybe (Left 12)+-- Just 12+--+-- >>> leftToMaybe (Right 12)+-- Nothing+leftToMaybe :: Either a b -> Maybe a+leftToMaybe = either Just (const Nothing)++-- | Maybe get the 'Right' side of an 'Either'.+--+-- @+-- 'rightToMaybe' ≡ 'either' ('const' 'Nothing') 'Just'+-- @+--+-- Using @Control.Lens@:+--+-- @+-- 'rightToMaybe' ≡ preview _Right+-- 'rightToMaybe' x ≡ x^?_Right+-- @+--+-- >>> rightToMaybe (Left 12)+-- Nothing+--+-- >>> rightToMaybe (Right 12)+-- Just 12+rightToMaybe :: Either a b -> Maybe b+rightToMaybe = either (const Nothing) Just