-- |
-- Convert bijections to and from (total) 'P.Iso'.
{-# LANGUAGE TypeOperators #-}
module Data.Invertible.PartialIsomorphism
  ( toIso
  , fromIso
  , (<$>)
  ) where

import Prelude hiding ((<$>))

import Data.Invertible.Bijection
import qualified Control.Isomorphism.Partial as P
import qualified Control.Isomorphism.Partial.Unsafe as P

-- |Convert a bijection to a (total) partial isomorphism.
toIso :: a <-> b -> P.Iso a b
toIso :: forall a b. (a <-> b) -> Iso a b
toIso (a -> b
f :<->: b -> a
g) = forall alpha beta.
(alpha -> Maybe beta) -> (beta -> Maybe alpha) -> Iso alpha beta
P.Iso (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> a
g)

-- |Convert a partial isomorphism to a bijection by propagating 'Nothing's.
fromIso :: P.Iso a b -> Maybe a <-> Maybe b
fromIso :: forall a b. Iso a b -> Maybe a <-> Maybe b
fromIso (P.Iso a -> Maybe b
f b -> Maybe a
g) = (a -> Maybe b
f forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<) forall (a :: * -> * -> *) b c. a b c -> a c b -> Bijection a b c
:<->: (b -> Maybe a
g forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<)

-- |Apply a bijection over a 'P.IsoFunctor' using 'P.<$>'.
(<$>) :: P.IsoFunctor f => a <-> b -> f a -> f b
<$> :: forall (f :: * -> *) a b. IsoFunctor f => (a <-> b) -> f a -> f b
(<$>) = forall (f :: * -> *) alpha beta.
IsoFunctor f =>
Iso alpha beta -> f alpha -> f beta
(P.<$>) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a <-> b) -> Iso a b
toIso