-- |
-- 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 = Bijection (->) a a
forall a. a <-> a
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
(.) = Bijection (->) b c -> Bijection (->) a b -> Bijection (->) 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 = b -> a -> b
forall a b. a -> b -> a
F.const b
b (a -> b) -> (b -> a) -> Bijection (->) a b
forall (a :: * -> * -> *) b c. a b c -> a c b -> Bijection a b c
:<->: a -> b -> a
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 = () -> a -> () <-> a
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 = (a -> b -> c) -> b -> a -> c
forall a b c. (a -> b -> c) -> b -> a -> c
F.flip ((a -> b -> c) -> b -> a -> c)
-> ((b -> a -> c) -> (a -> b -> c))
-> Bijection (->) (a -> b -> c) (b -> a -> c)
forall (a :: * -> * -> *) b c. a b c -> a c b -> Bijection a b c
:<->: (b -> a -> c) -> (a -> b -> c)
forall a b c. (a -> b -> c) -> b -> a -> c
F.flip