-- |Some utilities for working with 'Either'.
module Incipit.Either where

import Incipit.Base

-- |Turn 'Left' into 'Just' and 'Right' into 'Nothing'.
leftToMaybe :: Either l r -> Maybe l
leftToMaybe :: forall l r. Either l r -> Maybe l
leftToMaybe = (l -> Maybe l) -> (r -> Maybe l) -> Either l r -> Maybe l
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either l -> Maybe l
forall a. a -> Maybe a
Just (Maybe l -> r -> Maybe l
forall a b. a -> b -> a
const Maybe l
forall a. Maybe a
Nothing)
{-# inline leftToMaybe #-}

-- |Turn 'Right' into 'Just' and 'Left' into 'Nothing'.
rightToMaybe :: Either l r -> Maybe r
rightToMaybe :: forall l r. Either l r -> Maybe r
rightToMaybe = (l -> Maybe r) -> (r -> Maybe r) -> Either l r -> Maybe r
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe r -> l -> Maybe r
forall a b. a -> b -> a
const Maybe r
forall a. Maybe a
Nothing) r -> Maybe r
forall a. a -> Maybe a
Just
{-# inline rightToMaybe #-}

-- |Turn 'Just' into 'Right' and 'Nothing' into 'Left' with the supplied value.
maybeToRight :: l -> Maybe r -> Either l r
maybeToRight :: forall l r. l -> Maybe r -> Either l r
maybeToRight l
l = Either l r -> (r -> Either l r) -> Maybe r -> Either l r
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (l -> Either l r
forall a b. a -> Either a b
Left l
l) r -> Either l r
forall a b. b -> Either a b
Right
{-# inline maybeToRight #-}

-- |Turn 'Just' into 'Left' and 'Nothing' into 'Right' with the supplied value.
maybeToLeft :: r -> Maybe l -> Either l r
maybeToLeft :: forall r l. r -> Maybe l -> Either l r
maybeToLeft r
r = Either l r -> (l -> Either l r) -> Maybe l -> Either l r
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (r -> Either l r
forall a b. b -> Either a b
Right r
r) l -> Either l r
forall a b. a -> Either a b
Left
{-# inline maybeToLeft #-}

-- |Extract the value from either side of an 'Either'.
unify :: Either a a -> a
unify :: forall a. Either a a -> a
unify =
  (a -> a) -> (a -> a) -> Either a a -> a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either a -> a
forall a. a -> a
id a -> a
forall a. a -> a
id
{-# inline unify #-}

-- |Run an applicative action on the 'Left' side of an 'Either' to unify the types.
leftA ::
  Applicative m =>
  (a -> m b) ->
  Either a b ->
  m b
leftA :: forall (m :: * -> *) a b.
Applicative m =>
(a -> m b) -> Either a b -> m b
leftA a -> m b
f = \case
  Right b
b -> b -> m b
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
b
  Left a
a -> a -> m b
f a
a
{-# inline leftA #-}