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").
Examples
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 Int
>>> s
Left "foo"
>>> let n = Right 3 :: Either String Int
>>> n
Right 3
>>> :type s
s :: Either String Int
>>> :type n
n :: 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 Int
>>> let n = Right 3 :: Either String Int
>>> fmap (*2) s
Left "foo"
>>> fmap (*2) n
Right 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)
>>> :}
>>> parseMultiple
Right 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)
>>> :}
>>> parseMultiple
Left "parse error"