{-# LANGUAGE TypeOperators, CPP #-}
{-# OPTIONS_GHC -Wall #-}
module Data.Bijection
(
Bijection(..),(:<->:)
, idb, inverse, bimap, (--->)
, inBi
) where
#if __GLASGOW_HASKELL__ >= 609
import Control.Category
import Prelude hiding ((.), id)
#endif
import Control.Arrow
infix 8 :<->:
infixr 2 --->
data Bijection j a b = Bi { biTo :: a `j` b, biFrom :: b `j` a }
type a :<->: b = Bijection (->) a b
idb :: Arrow j => Bijection j a a
idb = Bi idA idA where idA = arr id
inverse :: Bijection j a b -> Bijection j b a
inverse (Bi ab ba) = Bi ba ab
#if __GLASGOW_HASKELL__ >= 609
instance Category j => Category (Bijection j) where
id = Bi id id
Bi bc cb . Bi ab ba = Bi (bc . ab) (ba . cb)
#endif
instance Arrow j => Arrow (Bijection j) where
#if __GLASGOW_HASKELL__ < 609
Bi ab ba >>> Bi bc cb = Bi (ab >>> bc) (cb >>> ba)
#endif
arr = error "No arr for (:<->:)."
first (Bi ab ba) = Bi (first ab) (first ba)
second (Bi ab ba) = Bi (second ab) (second ba)
Bi ab ba *** Bi cd dc = Bi (ab *** cd) (ba *** dc)
(&&&) = error "No (***) for (:<->:)"
bimap :: Functor f => (a :<->: b) -> (f a :<->: f b)
bimap (Bi ab ba) = Bi (fmap ab) (fmap ba)
(--->) :: Arrow j => Bijection j a b -> Bijection j c d
-> (a `j` c) :<->: (b `j` d)
Bi ab ba ---> Bi cd dc = Bi (\ ac -> ba>>>ac>>>cd) (\ bd -> ab>>>bd>>>dc)
inBi :: Arrow j => Bijection j a b -> (a `j` a) -> (b `j` b)
inBi (Bi to from) aa = from >>> aa >>> to