-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Partial isomorphisms -- -- Partial isomorphisms @package Piso @version 0.2 module Data.Piso -- | Bidirectional isomorphism that is total when applied in the forward -- direction (a -> b), but partial when applied in the -- backward direction (b -> Maybe a). -- -- This can be used to express constructor-deconstructor pairs. For -- example: -- --
--   nil :: Piso t ([a] :- t)
--   nil = Piso f g
--     where
--       f        t  = [] :- t
--       g ([] :- t) = Just t
--       g _         = Nothing
--   
--   cons :: Piso (a :- [a] :- t) ([a] :- t)
--   cons = Piso f g
--     where
--       f (x :- xs  :- t) = (x : xs) :- t
--       g ((x : xs) :- t) = Just (x :- xs :- t)
--       g _               = Nothing
--   
-- -- Here :- can be read as 'cons', forming a stack of values. For -- example, nil pushes [] onto the stack; or, in the -- backward direction, tries to remove [] from the stack. -- Representing constructor-destructor pairs as stack manipulators allows -- them to be composed more easily. -- -- Module Data.Piso.Common contains Pisos for some -- common datatypes. -- -- Modules Data.Piso.Generic and Data.Piso.TH offer -- generic ways of deriving Pisos for custom datatypes. data Piso a b Piso :: (a -> b) -> (b -> Maybe a) -> Piso a b -- | Apply an isomorphism in forward direction. forward :: Piso a b -> a -> b -- | Apply an isomorphism in backward direction. backward :: Piso a b -> b -> Maybe a -- | A type class that expresses that a category is able to embed -- Piso values. class Category cat => FromPiso cat fromPiso :: FromPiso cat => Piso a b -> cat a b -- | Heterogenous stack with a head and a tail. Or: an infix way to write -- (,). data (:-) h t (:-) :: h -> t -> (:-) h t instance GHC.Base.Functor ((Data.Piso.:-) h) instance (GHC.Show.Show t, GHC.Show.Show h) => GHC.Show.Show (h Data.Piso.:- t) instance (GHC.Classes.Eq t, GHC.Classes.Eq h) => GHC.Classes.Eq (h Data.Piso.:- t) instance Control.Category.Category Data.Piso.Piso instance Data.Piso.FromPiso Data.Piso.Piso module Data.Piso.Generic -- | Derive a list of partial isomorphisms, one for each constructor in the -- Generic datatype a. The list is wrapped in the unary -- constructor PisoList. Within that constructor, the -- isomorphisms are separated by the right-associative binary infix -- constructor :&. Finally, the individual isomorphisms are -- wrapped in the unary constructor I. These constructors are -- all exported by this module, but no documentation is generated for -- them by Hackage. -- -- As an example, here is how to define the isomorphisms nil and -- cons for [a], which is an instance of -- Generic: -- --
--   nil  :: Piso              t  ([a] :- t)
--   cons :: Piso (a :- [a] :- t) ([a] :- t)
--   (nil, cons) = (nil', cons')
--     where
--       PisoList (I nil' :& I cons') = mkPisoList
--   
-- -- GHC 7.6.3 requires the extra indirection through nil' and -- cons', due to bug 7268 -- (http://ghc.haskell.org/trac/ghc/ticket/7268). When it is -- fixed, the example above can be written in a more direct way: -- --
--   nil  :: Piso              t  ([a] :- t)
--   cons :: Piso (a :- [a] :- t) ([a] :- t)
--   PisoList (I nil :& I cons) = mkPisoList
--   
-- -- If you are familiar with the generic representations from -- Data.Generic, you might be interested in the exact types of -- the various constructors in which the isomorphisms are wrapped: -- --
--   I        :: (forall t. Piso (PisoLhs f t) (a :- t)) -> PisoList (M1 C c f) a
--   (:&)     :: PisoList f a -> PisoList g a -> PisoList (f :+: g) a
--   PisoList :: PisoList f a -> PisoList (M1 D c f) a
--   
-- -- The type constructor PisoLhs that appears in the type of -- I is an internal type family that builds the proper -- heterogenous list of types (using :-) based on the -- constructor's fields. mkPisoList :: (Generic a, MkPisoList (Rep a)) => PisoList (Rep a) a instance Data.Piso.Generic.MkPisoList f => Data.Piso.Generic.MkPisoList (GHC.Generics.M1 GHC.Generics.D c f) instance (Data.Piso.Generic.MkPisoList f, Data.Piso.Generic.MkPisoList g) => Data.Piso.Generic.MkPisoList (f GHC.Generics.:+: g) instance Data.Piso.Generic.MkPiso f => Data.Piso.Generic.MkPisoList (GHC.Generics.M1 GHC.Generics.C c f) instance Data.Piso.Generic.MkPiso GHC.Generics.U1 instance Data.Piso.Generic.MkPiso (GHC.Generics.K1 i a) instance Data.Piso.Generic.MkPiso f => Data.Piso.Generic.MkPiso (GHC.Generics.M1 i c f) instance (Data.Piso.Generic.MkPiso f, Data.Piso.Generic.MkPiso g) => Data.Piso.Generic.MkPiso (f GHC.Generics.:*: g) module Data.Piso.TH -- | Derive partial isomorphisms for a given datatype. The resulting -- expression is a tuple with one isomorphism element for each -- constructor in the datatype. -- -- For example: -- --
--   nothing :: Piso t (Maybe a :- t)
--   just    :: Piso (a :- t) (Maybe a :- t)
--   (nothing, just) = $(derivePisos ''Maybe)
--   
-- -- Deriving isomorphisms this way requires -XNoMonoPatBinds. derivePisos :: Name -> Q Exp -- | Constructor-destructor isomorphisms for some common datatypes. module Data.Piso.Common unit :: Piso t (() :- t) tup :: Piso (a :- (b :- t)) ((a, b) :- t) tup3 :: Piso (a :- (b :- (c :- t))) ((a, b, c) :- t) nothing :: Piso t (Maybe a :- t) just :: Piso (a :- t) (Maybe a :- t) nil :: Piso t ([a] :- t) cons :: Piso (a :- ([a] :- t)) ([a] :- t) left :: Piso (a :- t) (Either a b :- t) right :: Piso (b :- t) (Either a b :- t) false :: Piso t (Bool :- t) true :: Piso t (Bool :- t)