-- |
-- Bidirectional version of "Data.Function".
{-# LANGUAGE Safe, TypeOperators #-}
module Data.Invertible.Function
  ( id
  , (.)
  , consts
  , const
  , flip
  ) where

import Prelude hiding (id, (.), const, flip)
import qualified Control.Category as C
import qualified Data.Function as F

import Data.Invertible.Bijection

-- |Identity bijection.
id :: a <-> a
id :: forall a. a <-> a
id = forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
C.id

-- |Bijection composition
(.) :: (b <-> c) -> (a <-> b) -> a <-> c
. :: forall b c a. (b <-> c) -> (a <-> b) -> a <-> c
(.) = forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
(C..)
infixr 9 .

-- |Bidirectional constant function (not a true bijection).
consts :: a -> b -> a <-> b
consts :: forall a b. a -> b -> a <-> b
consts a
a b
b = forall a b. a -> b -> a
F.const b
b forall (a :: * -> * -> *) b c. a b c -> a c b -> Bijection a b c
:<->: forall a b. a -> b -> a
F.const a
a

-- |Convert between '()' and a constant (not a true bijection).
const :: a -> () <-> a
const :: forall a. a -> () <-> a
const = forall a b. a -> b -> a <-> b
consts ()

-- |'F.flip' the order of the first two arguments of a function.
flip :: (a -> b -> c) <-> (b -> a -> c)
flip :: forall a b c. (a -> b -> c) <-> (b -> a -> c)
flip = forall a b c. (a -> b -> c) -> b -> a -> c
F.flip forall (a :: * -> * -> *) b c. a b c -> a c b -> Bijection a b c
:<->: forall a b c. (a -> b -> c) -> b -> a -> c
F.flip