-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Strict.Either
-- Copyright   :  (c) 2006-2007 Roman Leshchinskiy
-- License     :  BSD-style (see the file LICENSE)
-- 
-- Maintainer  :  Roman Leshchinskiy <rl@cse.unsw.edu.au>
-- Stability   :  experimental
-- Portability :  portable
--
-- Strict @Either@.
--
-- Same as the standard Haskell @Either@, but @Left _|_ = Right _|_ = _|_@
--
-----------------------------------------------------------------------------

module Data.Strict.Either (
    Either(..)
  , either
  , isLeft, isRight
  , fromLeft, fromRight
) where

import Prelude hiding( Either(..), either )

-- | The strict choice type.
data Either a b = Left !a | Right !b deriving(Either a b -> Either a b -> Bool
(Either a b -> Either a b -> Bool)
-> (Either a b -> Either a b -> Bool) -> Eq (Either a b)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall a b. (Eq a, Eq b) => Either a b -> Either a b -> Bool
/= :: Either a b -> Either a b -> Bool
$c/= :: forall a b. (Eq a, Eq b) => Either a b -> Either a b -> Bool
== :: Either a b -> Either a b -> Bool
$c== :: forall a b. (Eq a, Eq b) => Either a b -> Either a b -> Bool
Eq, Eq (Either a b)
Eq (Either a b) =>
(Either a b -> Either a b -> Ordering)
-> (Either a b -> Either a b -> Bool)
-> (Either a b -> Either a b -> Bool)
-> (Either a b -> Either a b -> Bool)
-> (Either a b -> Either a b -> Bool)
-> (Either a b -> Either a b -> Either a b)
-> (Either a b -> Either a b -> Either a b)
-> Ord (Either a b)
Either a b -> Either a b -> Bool
Either a b -> Either a b -> Ordering
Either a b -> Either a b -> Either a b
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a b. (Ord a, Ord b) => Eq (Either a b)
forall a b. (Ord a, Ord b) => Either a b -> Either a b -> Bool
forall a b. (Ord a, Ord b) => Either a b -> Either a b -> Ordering
forall a b.
(Ord a, Ord b) =>
Either a b -> Either a b -> Either a b
min :: Either a b -> Either a b -> Either a b
$cmin :: forall a b.
(Ord a, Ord b) =>
Either a b -> Either a b -> Either a b
max :: Either a b -> Either a b -> Either a b
$cmax :: forall a b.
(Ord a, Ord b) =>
Either a b -> Either a b -> Either a b
>= :: Either a b -> Either a b -> Bool
$c>= :: forall a b. (Ord a, Ord b) => Either a b -> Either a b -> Bool
> :: Either a b -> Either a b -> Bool
$c> :: forall a b. (Ord a, Ord b) => Either a b -> Either a b -> Bool
<= :: Either a b -> Either a b -> Bool
$c<= :: forall a b. (Ord a, Ord b) => Either a b -> Either a b -> Bool
< :: Either a b -> Either a b -> Bool
$c< :: forall a b. (Ord a, Ord b) => Either a b -> Either a b -> Bool
compare :: Either a b -> Either a b -> Ordering
$ccompare :: forall a b. (Ord a, Ord b) => Either a b -> Either a b -> Ordering
$cp1Ord :: forall a b. (Ord a, Ord b) => Eq (Either a b)
Ord, ReadPrec [Either a b]
ReadPrec (Either a b)
Int -> ReadS (Either a b)
ReadS [Either a b]
(Int -> ReadS (Either a b))
-> ReadS [Either a b]
-> ReadPrec (Either a b)
-> ReadPrec [Either a b]
-> Read (Either a b)
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
forall a b. (Read a, Read b) => ReadPrec [Either a b]
forall a b. (Read a, Read b) => ReadPrec (Either a b)
forall a b. (Read a, Read b) => Int -> ReadS (Either a b)
forall a b. (Read a, Read b) => ReadS [Either a b]
readListPrec :: ReadPrec [Either a b]
$creadListPrec :: forall a b. (Read a, Read b) => ReadPrec [Either a b]
readPrec :: ReadPrec (Either a b)
$creadPrec :: forall a b. (Read a, Read b) => ReadPrec (Either a b)
readList :: ReadS [Either a b]
$creadList :: forall a b. (Read a, Read b) => ReadS [Either a b]
readsPrec :: Int -> ReadS (Either a b)
$creadsPrec :: forall a b. (Read a, Read b) => Int -> ReadS (Either a b)
Read, Int -> Either a b -> ShowS
[Either a b] -> ShowS
Either a b -> String
(Int -> Either a b -> ShowS)
-> (Either a b -> String)
-> ([Either a b] -> ShowS)
-> Show (Either a b)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall a b. (Show a, Show b) => Int -> Either a b -> ShowS
forall a b. (Show a, Show b) => [Either a b] -> ShowS
forall a b. (Show a, Show b) => Either a b -> String
showList :: [Either a b] -> ShowS
$cshowList :: forall a b. (Show a, Show b) => [Either a b] -> ShowS
show :: Either a b -> String
$cshow :: forall a b. (Show a, Show b) => Either a b -> String
showsPrec :: Int -> Either a b -> ShowS
$cshowsPrec :: forall a b. (Show a, Show b) => Int -> Either a b -> ShowS
Show)

instance Functor (Either a) where
  fmap :: (a -> b) -> Either a a -> Either a b
fmap _ (Left  x :: a
x) = a -> Either a b
forall a b. a -> Either a b
Left a
x
  fmap f :: a -> b
f (Right y :: a
y) = b -> Either a b
forall a b. b -> Either a b
Right (a -> b
f a
y)

-- | Case analysis: if the value is @'Left' a@, apply the first function to @a@;
-- if it is @'Right' b@, apply the second function to @b@.
either :: (a -> c) -> (b -> c) -> Either a b -> c
either :: (a -> c) -> (b -> c) -> Either a b -> c
either f :: a -> c
f _ (Left  x :: a
x) = a -> c
f a
x
either _ g :: b -> c
g (Right y :: b
y) = b -> c
g b
y

-- | Yields 'True' iff the argument is of the form @Left _@.
--
isLeft :: Either a b -> Bool
isLeft :: Either a b -> Bool
isLeft (Left _) = Bool
True
isLeft _        = Bool
False

-- | Yields 'True' iff the argument is of the form @Right _@.
--
isRight :: Either a b -> Bool
isRight :: Either a b -> Bool
isRight (Right _) = Bool
True
isRight _         = Bool
False

-- | Extracts the element out of a 'Left' and throws an error if the argument
-- is a 'Right'.
fromLeft :: Either a b -> a
fromLeft :: Either a b -> a
fromLeft (Left x :: a
x) = a
x
fromLeft _        = String -> a
forall a. HasCallStack => String -> a
error "Data.Strict.Either.fromLeft: Right"

-- | Extracts the element out of a 'Right' and throws an error if the argument
-- is a 'Left'.
fromRight :: Either a b -> b
fromRight :: Either a b -> b
fromRight (Right x :: b
x) = b
x
fromRight _         = String -> b
forall a. HasCallStack => String -> a
error "Data.Strict.Either.fromRight: Left"