-- |
-- Bidirectional version of "Data.Functor".
{-# LANGUAGE Safe, QuasiQuotes, TypeOperators #-}
module Data.Invertible.Functor
  ( bifmap
  , identity
  ) where

import Prelude hiding (fmap, (<$>))
import qualified Data.Functor as F
import Data.Functor.Identity (Identity(..))

import Data.Invertible.Bijection
import Data.Invertible.TH

-- |Lift both sides of an bijection over a functor using 'F.fmap'.
-- We name this bifmap in deference to the more useful 'Control.Invertible.Functor.fmap'.
bifmap :: Functor f => a <-> b -> f a <-> f b
bifmap :: forall (f :: * -> *) a b. Functor f => (a <-> b) -> f a <-> f b
bifmap (a -> b
f :<->: b -> a
g) = (a -> b) -> f a -> f b
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
F.fmap a -> b
f (f a -> f b) -> (f b -> f a) -> Bijection (->) (f a) (f b)
forall (a :: * -> * -> *) b c. a b c -> a c b -> Bijection a b c
:<->: (b -> a) -> f b -> f a
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
F.fmap b -> a
g

-- |Convert the 'Identity' functor.
identity :: a <-> Identity a
identity :: forall a. a <-> Identity a
identity = [biCase|a <-> Identity a|]