-- |
-- 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) = (a -> Maybe b) -> (b -> Maybe a) -> Iso a b
forall alpha beta.
(alpha -> Maybe beta) -> (beta -> Maybe alpha) -> Iso alpha beta
P.Iso (b -> Maybe b
forall a. a -> Maybe a
Just (b -> Maybe b) -> (a -> b) -> a -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> (b -> a) -> b -> Maybe a
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 (a -> Maybe b) -> Maybe a -> Maybe b
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<) (Maybe a -> Maybe b)
-> (Maybe b -> Maybe a) -> Bijection (->) (Maybe a) (Maybe b)
forall (a :: * -> * -> *) b c. a b c -> a c b -> Bijection a b c
:<->: (b -> Maybe a
g (b -> Maybe a) -> Maybe b -> Maybe a
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
(<$>) = Iso a b -> f a -> f b
forall alpha beta. Iso alpha beta -> f alpha -> f beta
forall (f :: * -> *) alpha beta.
IsoFunctor f =>
Iso alpha beta -> f alpha -> f beta
(P.<$>) (Iso a b -> f a -> f b)
-> ((a <-> b) -> Iso a b) -> (a <-> b) -> f a -> f b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a <-> b) -> Iso a b
forall a b. (a <-> b) -> Iso a b
toIso