```{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE NoMonoPatBinds #-}

-- | Constructor-destructor isomorphisms for some common datatypes.
module Data.Piso.Common (

-- * @()@
unit,

-- * @(,)@
tup,

-- * @(,,)@
tup3,

-- * @Maybe a@
nothing, just,

-- * @[a]@
nil, cons,

-- * @Either a b@
left, right,

-- * @Bool@
false, true

) where

import Prelude hiding (id, (.), maybe, either)

import Data.Piso
import Data.Piso.TH

unit :: Piso t (() :- t)
unit = \$(derivePisos ''())

tup :: Piso (a :- b :- t) ((a, b) :- t)
tup = \$(derivePisos ''(,))

tup3 :: Piso (a :- b :- c :- t) ((a, b, c) :- t)
tup3 = \$(derivePisos ''(,,))

nothing :: Piso t (Maybe a :- t)
just    :: Piso (a :- t) (Maybe a :- t)
(nothing, just) = \$(derivePisos ''Maybe)

nil :: Piso t ([a] :- t)
nil = Piso f g
where
f        t  = [] :- t
g ([] :- t) = Just t
g _         = Nothing

cons :: Piso (a :- [a] :- t) ([a] :- t)
cons = Piso f g
where
f (x :- xs  :- t) = (x : xs) :- t
g ((x : xs) :- t) = Just (x :- xs :- t)
g _               = Nothing

left  :: Piso (a :- t) (Either a b :- t)
right :: Piso (b :- t) (Either a b :- t)
(left, right) = \$(derivePisos ''Either)

false :: Piso t (Bool :- t)
true  :: Piso t (Bool :- t)
(false, true) = \$(derivePisos ''Bool)
```