2013-03-10 08:54:37 +00:00
|
|
|
module Either where
|
|
|
|
|
2013-09-08 22:08:02 +00:00
|
|
|
{-| Represents any data that can take two different types.
|
|
|
|
|
|
|
|
# Type and Constructors
|
2013-09-09 22:59:05 +00:00
|
|
|
@docs Either
|
2013-09-08 22:08:02 +00:00
|
|
|
|
|
|
|
# Taking Eithers apart
|
|
|
|
@docs either, isLeft, isRight
|
|
|
|
|
|
|
|
# Eithers and Lists
|
2013-10-18 03:54:55 +00:00
|
|
|
@docs lefts, rights, partition
|
2013-09-08 22:08:02 +00:00
|
|
|
|
|
|
|
-}
|
|
|
|
|
2013-03-11 05:42:57 +00:00
|
|
|
import List
|
2013-03-10 08:54:37 +00:00
|
|
|
|
2013-09-09 22:59:05 +00:00
|
|
|
{-| Represents any data may take two forms. For example, a user ID may be
|
|
|
|
either an `Int` or a `String`.
|
|
|
|
|
|
|
|
This can also be used for error handling `(Either String a)` where
|
|
|
|
error messages are stored on the left, and the correct values
|
|
|
|
(“right” values) are stored on the right.
|
2013-09-08 22:08:02 +00:00
|
|
|
-}
|
2013-01-09 10:07:46 +00:00
|
|
|
data Either a b = Left a | Right b
|
|
|
|
|
2013-09-08 22:08:02 +00:00
|
|
|
{-| Apply the first function to a `Left` and the second function to a `Right`.
|
2013-10-18 03:54:55 +00:00
|
|
|
This allows the extraction of a value from an `Either`.
|
2014-02-18 23:33:21 +00:00
|
|
|
|
|
|
|
either (\n -> n + 1) sqrt (Left 4) == 5
|
|
|
|
either (\n -> n + 1) sqrt (Right 4) == 2
|
|
|
|
|
|
|
|
map : (a -> b) -> Either err a -> Either err b
|
|
|
|
map f e = either Left (\x -> Right (f x)) e
|
2013-09-08 22:08:02 +00:00
|
|
|
-}
|
2013-02-07 18:54:21 +00:00
|
|
|
either : (a -> c) -> (b -> c) -> Either a b -> c
|
2013-01-09 10:07:46 +00:00
|
|
|
either f g e = case e of { Left x -> f x ; Right y -> g y }
|
|
|
|
|
2014-02-18 23:33:21 +00:00
|
|
|
{-| True if the value is a `Left`.
|
|
|
|
|
|
|
|
isLeft (Left "Cat") == True
|
|
|
|
isLeft (Right 1123) == False
|
|
|
|
-}
|
2013-03-11 05:42:57 +00:00
|
|
|
isLeft : Either a b -> Bool
|
|
|
|
isLeft e = case e of { Left _ -> True ; _ -> False }
|
2013-02-07 18:54:21 +00:00
|
|
|
|
2014-02-18 23:33:21 +00:00
|
|
|
{-| True if the value is a `Right`.
|
|
|
|
|
|
|
|
isRight (Left "Cat") == False
|
|
|
|
isRight (Right 1123) == True
|
|
|
|
-}
|
2013-02-07 18:54:21 +00:00
|
|
|
isRight : Either a b -> Bool
|
2013-01-09 10:07:46 +00:00
|
|
|
isRight e = case e of { Right _ -> True ; _ -> False }
|
|
|
|
|
2014-02-18 23:33:21 +00:00
|
|
|
{-| Keep only the values held in `Left` values.
|
|
|
|
|
|
|
|
lefts [Left 3, Right 'a', Left 5, Right "eight"] == [3,5]
|
|
|
|
-}
|
2013-04-22 09:36:11 +00:00
|
|
|
lefts : [Either a b] -> [a]
|
2013-05-06 09:30:50 +00:00
|
|
|
lefts es = List.foldr consLeft [] es
|
2013-02-07 18:54:21 +00:00
|
|
|
|
2014-02-18 23:33:21 +00:00
|
|
|
{-| Keep only the values held in `Right` values.
|
|
|
|
|
|
|
|
rights [Left 3, Right 'a', Left 5, Right 'b'] == ['a','b']
|
|
|
|
-}
|
2013-04-22 09:36:11 +00:00
|
|
|
rights : [Either a b] -> [b]
|
2013-05-06 09:30:50 +00:00
|
|
|
rights es = List.foldr consRight [] es
|
2013-01-09 10:07:46 +00:00
|
|
|
|
2013-09-08 22:08:02 +00:00
|
|
|
{-| Split into two lists, lefts on the left and rights on the right. So we
|
2013-10-18 03:54:55 +00:00
|
|
|
have the equivalence: `(partition es == (lefts es, rights es))`
|
2014-02-18 23:33:21 +00:00
|
|
|
|
|
|
|
partition [Left 3, Right 'a', Left 5, Right 'b'] == ([3,5],['a','b'])
|
2013-09-08 22:08:02 +00:00
|
|
|
-}
|
2013-04-22 09:36:11 +00:00
|
|
|
partition : [Either a b] -> ([a],[b])
|
2013-05-06 09:30:50 +00:00
|
|
|
partition es = List.foldr consEither ([],[]) es
|
|
|
|
|
|
|
|
consLeft e vs =
|
|
|
|
case e of
|
|
|
|
Left v -> v::vs
|
|
|
|
Right _ -> vs
|
|
|
|
|
|
|
|
consRight e vs =
|
|
|
|
case e of
|
|
|
|
Left _ -> vs
|
|
|
|
Right v -> v::vs
|
|
|
|
|
|
|
|
consEither e (ls,rs) =
|
|
|
|
case e of
|
|
|
|
Left l -> (l::ls,rs)
|
|
|
|
Right r -> (ls,r::rs)
|