Return the contents of a Left-value or a default value otherwise.
Examples
Basic usage:
fromLeft 1 (Left 3)3fromLeft 1 (Right "foo")1
:: a typeCtrl KGHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27
Moduleextra-1.8Haskell2010
This module extends Data.Either with extra operations, particularly to quickly extract from inside an Either. Some of these operations are partial, and should be used with care in production-quality code.
Return the contents of a Left-value or a default value otherwise.
Basic usage:
fromLeft 1 (Left 3)3fromLeft 1 (Right "foo")1
Return the contents of a Right-value or a default value otherwise.
Basic usage:
fromRight 1 (Right 3)3fromRight 1 (Left "foo")1
The Either type represents values with two possibilities: a value of
type Either a b is either Left a or Right b.
The Either type is sometimes used to represent a value which is either correct or an error; by convention, the Left constructor is used to hold an error value and the Right constructor is used to hold a correct value (mnemonic: "right" also means "correct").
The type Either String Int is the type of values which can be either
a String or an Int. The Left constructor can be used only on
Strings, and the Right constructor can be used only on Ints:
let s = Left "foo" :: Either String IntsLeft "foo"let n = Right 3 :: Either String IntnRight 3:type ss :: Either String Int:type nn :: Either String Int
The fmap from our Functor instance will ignore Left values, but will apply the supplied function to values contained in a Right:
let s = Left "foo" :: Either String Intlet n = Right 3 :: Either String Intfmap (*2) sLeft "foo"fmap (*2) nRight 6
The Monad instance for Either allows us to chain together multiple actions which may fail, and fail overall if any of the individual steps failed. First we'll write a function that can either parse an Int from a Char, or fail.
import Data.Char ( digitToInt, isDigit ):{ let parseEither :: Char -> Either String Int parseEither c | isDigit c = Right (digitToInt c) | otherwise = Left "parse error":}
The following should work, since both '1' and '2' can be
parsed as Ints.
:{ let parseMultiple :: Either String Int parseMultiple = do x <- parseEither '1' y <- parseEither '2' return (x + y):}
parseMultipleRight 3
But the following should fail overall, since the first operation where
we attempt to parse 'm' as an Int will fail:
:{ let parseMultiple :: Either String Int parseMultiple = do x <- parseEither 'm' y <- parseEither '2' return (x + y):}
parseMultipleLeft "parse error"
Bifoldable EitherDefined in base-4.20.2.0 · Data.BifoldableBifoldable1 EitherDefined in base-4.20.2.0 · Data.Bifoldable1Bifunctor EitherDefined in base-4.20.2.0 · Data.BifunctorBitraversable EitherDefined in base-4.20.2.0 · Data.BitraversableEq2 EitherDefined in base-4.20.2.0 · Data.Functor.ClassesOrd2 EitherDefined in base-4.20.2.0 · Data.Functor.ClassesRead2 EitherDefined in base-4.20.2.0 · Data.Functor.ClassesShow2 EitherDefined in base-4.20.2.0 · Data.Functor.ClassesNFData2 EitherDefined in deepseq-1.5.0.0 · Control.DeepSeqGeneric1 (Either a)Defined in ghc-internal-9.1003.0 · GHC.Internal.GenericsMonadError e (Either e)Defined in mtl-2.3.1 · Control.Monad.Error.Class(Lift a, Lift b) => Lift (Either a b)Defined in template-haskell-2.22.0.0 · Language.Haskell.TH.SyntaxMonad (Either e)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.EitherFunctor (Either a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.EitherMonadFix (Either e)Defined in ghc-internal-9.1003.0 · GHC.Internal.Control.Monad.FixApplicative (Either e)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.EitherFoldable (Either a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableTraversable (Either a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.TraversableEq a => Eq1 (Either a)Defined in base-4.20.2.0 · Data.Functor.ClassesOrd a => Ord1 (Either a)Defined in base-4.20.2.0 · Data.Functor.ClassesRead a => Read1 (Either a)Defined in base-4.20.2.0 · Data.Functor.ClassesShow a => Show1 (Either a)Defined in base-4.20.2.0 · Data.Functor.ClassesNFData a => NFData1 (Either a)Defined in deepseq-1.5.0.0 · Control.DeepSeqe ~ SomeException => MonadCatch (Either e)Defined in exceptions-0.10.9 · Control.Monad.Catche ~ SomeException => MonadMask (Either e)Defined in exceptions-0.10.9 · Control.Monad.Catche ~ SomeException => MonadThrow (Either e)Defined in exceptions-0.10.9 · Control.Monad.Catch(Eq a, Eq b) => Eq (Either a b)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Either(Data a, Data b) => Data (Either a b)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Data(Ord a, Ord b) => Ord (Either a b)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Either(Read a, Read b) => Read (Either a b)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Either(Show a, Show b) => Show (Either a b)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.EitherGeneric (Either a b)Defined in ghc-internal-9.1003.0 · GHC.Internal.GenericsSemigroup (Either a b)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Either(NFData a, NFData b) => NFData (Either a b)Defined in deepseq-1.5.0.0 · Control.DeepSeq(Pretty a, Pretty b) => Pretty (Either a b)Defined in pretty-1.1.3.6 · Text.PrettyPrint.Annotated.HughesPJClass(Pretty a, Pretty b) => Pretty (Either a b)Defined in pretty-1.1.3.6 · Text.PrettyPrint.HughesPJClasstype Rep (Either a b) = D1 ('MetaData "Either"
"GHC.Internal.Data.Either"
"ghc-internal"
'False) (C1 ('MetaCons "Left"
'PrefixI 'False) (S1 ('MetaSel 'Nothing 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 a)) :+: C1 ('MetaCons "Right"
'PrefixI 'False) (S1 ('MetaSel 'Nothing 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 b)))Defined in ghc-internal-9.1003.0 · GHC.Internal.Genericstype Rep1 (Either a) = D1 ('MetaData "Either"
"GHC.Internal.Data.Either"
"ghc-internal"
'False) (C1 ('MetaCons "Left"
'PrefixI 'False) (S1 ('MetaSel 'Nothing 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 a)) :+: C1 ('MetaCons "Right"
'PrefixI 'False) (S1 ('MetaSel 'Nothing 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) Par1))Defined in ghc-internal-9.1003.0 · GHC.Internal.GenericsCase analysis for the Either type.
If the value is Left a, apply the first function to a;
if it is Right b, apply the second function to b.
We create two values of type Either String Int, one using the
Left constructor and another using the Right constructor. Then
we apply "either" the Prelude.length function (if we have a String)
or the "times-two" function (if we have an Int):
let s = Left "foo" :: Either String Intlet n = Right 3 :: Either String Inteither length (*2) s3either length (*2) n6
Return True if the given value is a Left-value, False otherwise.
Basic usage:
isLeft (Left "foo")TrueisLeft (Right 3)False
Assuming a Left value signifies some sort of error, we can use isLeft to write a very simple error-reporting function that does absolutely nothing in the case of success, and outputs "ERROR" if any error occurred.
This example shows how isLeft might be used to avoid pattern matching when one does not care about the value contained in the constructor:
import Control.Monad ( when )let report e = when (isLeft e) $ putStrLn "ERROR"report (Right 1)report (Left "parse error")ERROR
Return True if the given value is a Right-value, False otherwise.
Basic usage:
isRight (Left "foo")FalseisRight (Right 3)True
Assuming a Left value signifies some sort of error, we can use isRight to write a very simple reporting function that only outputs "SUCCESS" when a computation has succeeded.
This example shows how isRight might be used to avoid pattern matching when one does not care about the value contained in the constructor:
import Control.Monad ( when )let report e = when (isRight e) $ putStrLn "SUCCESS"report (Left "parse error")report (Right 1)SUCCESS
Partitions a list of Either into two lists. All the Left elements are extracted, in order, to the first component of the output. Similarly the Right elements are extracted to the second component of the output.
Basic usage:
let list = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ]partitionEithers list(["foo","bar","baz"],[3,7])
The pair returned by partitionEithers x should be the same
pair as (lefts x, rights x):
let list = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ]partitionEithers list == (lefts list, rights list)True
Return the contents of a Left-value or a default value otherwise.
Basic usage:
fromLeft 1 (Left 3)3fromLeft 1 (Right "foo")1
Return the contents of a Right-value or a default value otherwise.
Basic usage:
fromRight 1 (Right 3)3fromRight 1 (Left "foo")1
Pull the value out of an Either where both alternatives have the same type.
\x -> fromEither (Left x ) == x
\x -> fromEither (Right x) == xThe fromRight' function extracts the element out of a Right and
throws an error if its argument is Left.
Much like fromJust, using this function in polished code is usually a bad idea.
\x -> fromRight' (Right x) == x
\x -> fromRight' (Left x) == undefined