{-# LANGUAGE GADTs, StandaloneDeriving #-}

-- |

-- Module      : OAlg.Data.Either

-- Description : disjoint union of data

-- Copyright   : (c) Erich Gut

-- License     : BSD3

-- Maintainer  : zerich.gut@gmail.com

--

-- disjoint union of data.

module OAlg.Data.Either
  ( -- * Either

    Either(..), either

    -- * Either1

  , Either1(..), either1
  
    -- * Either2

  , Either2(..)
  )
  where 

import OAlg.Data.Show
import OAlg.Data.Equal

--------------------------------------------------------------------------------

-- Either1 -


-- | disjoint union of two 1-parameterized data types.

data Either1 f g x where
  Left1  :: f x -> Either1 f g x
  Right1 :: g x -> Either1 f g x

deriving instance (Show (f x), Show (g x)) => Show (Either1 f g x)
deriving instance (Eq (f x), Eq (g x)) => Eq (Either1 f g x)

{-
instance (Show1 f, Show1 g) => Show1 (Either1 f g) where
  show1 (Left1 f)  = "Left11 (" ++ show1 f ++ ")"
  show1 (Right1 g) = "Right1 (" ++ show1 g ++ ")"

instance (Show1 f, Show1 g) => Show (Either1 f g x) where
  show = show1

instance (Eq1 f, Eq1 g) => Eq1 (Either1 f g) where
  eq1 (Left1 x) (Left1 y)   = eq1 x y
  eq1 (Right1 x) (Right1 y) = eq1 x y
  eq1 _ _                   = False

instance (Eq1 f, Eq1 g) => Eq (Either1 f g x) where
  (==) = eq1
-}

--------------------------------------------------------------------------------

-- either1 -


-- | the induced map.

either1 :: (f x -> y) -> (g x -> y) -> Either1 f g x -> y
either1 :: forall (f :: * -> *) x y (g :: * -> *).
(f x -> y) -> (g x -> y) -> Either1 f g x -> y
either1 f x -> y
f g x -> y
_ (Left1 f x
fx)  = f x -> y
f f x
fx
either1 f x -> y
_ g x -> y
g (Right1 g x
gx) = g x -> y
g g x
gx

--------------------------------------------------------------------------------

-- Either2 -


-- | disjoint union of two 2-parameterized data types.

data Either2 f g a b where
  Left2 :: f a b -> Either2 f g a b
  Right2 :: g a b -> Either2 f g a b

--------------------------------------------------------------------------------

-- Either2 -


instance (Show2 f, Show2 g) => Show2 (Either2 f g) where
  show2 :: forall a b. Either2 f g a b -> String
show2 (Left2 f a b
f)  = String
"Left2 (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ f a b -> String
forall a b. f a b -> String
forall (h :: * -> * -> *) a b. Show2 h => h a b -> String
show2 f a b
f String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
  show2 (Right2 g a b
g) = String
"Right2 (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ g a b -> String
forall a b. g a b -> String
forall (h :: * -> * -> *) a b. Show2 h => h a b -> String
show2 g a b
g String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

instance (Show2 f, Show2 g) => Show (Either2 f g x y) where
  show :: Either2 f g x y -> String
show = Either2 f g x y -> String
forall a b. Either2 f g a b -> String
forall (h :: * -> * -> *) a b. Show2 h => h a b -> String
show2
  
instance (Eq2 f, Eq2 g) => Eq2 (Either2 f g) where
  eq2 :: forall x y. Either2 f g x y -> Either2 f g x y -> Bool
eq2 (Left2 f x y
f) (Left2 f x y
g)   = f x y -> f x y -> Bool
forall x y. f x y -> f x y -> Bool
forall (h :: * -> * -> *) x y. Eq2 h => h x y -> h x y -> Bool
eq2 f x y
f f x y
g
  eq2 (Right2 g x y
f) (Right2 g x y
g) = g x y -> g x y -> Bool
forall x y. g x y -> g x y -> Bool
forall (h :: * -> * -> *) x y. Eq2 h => h x y -> h x y -> Bool
eq2 g x y
f g x y
g
  eq2 Either2 f g x y
_ Either2 f g x y
_                   = Bool
False

instance (Eq2 f, Eq2 g) => Eq (Either2 f g x y) where
  == :: Either2 f g x y -> Either2 f g x y -> Bool
(==) = Either2 f g x y -> Either2 f g x y -> Bool
forall x y. Either2 f g x y -> Either2 f g x y -> Bool
forall (h :: * -> * -> *) x y. Eq2 h => h x y -> h x y -> Bool
eq2