-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Lightweight generic library for mutually recursive data types. -- -- Multiplate is an alternative extension of the Uniplate/Compos core -- library to support mutally recursive datatypes in a way that is as -- powerful as Compos, as easy to use as Biplate, and more portable than -- both of them. Multiplate does not require GADTs and does not require -- multi-parameter type classes. It only requires rank 3 polymorphism. @package multiplate @version 0.0.2 -- | Suppose we are given mutually recursive data types A, -- B, and C. Here are some definitions of terms. -- --
-- data ABCPlate f = ABCPlate
-- { fieldA :: A -> f A
-- , fieldB :: B -> f B
-- , fieldC :: C -> f C
-- }
--
--
-- Although this above is the original motivation behind multiplate,but
-- you can make any structure you want into a Multiplate as long
-- as you satisfy the two multiplate laws listed below.
--
-- The names of the functions in this module are based on Sebastian
-- Fischer's Refactoring Uniplate:
-- http://www-ps.informatik.uni-kiel.de/~sebf/projects/traversal.html
module Data.Generics.Multiplate
-- | A plate over f consists of several fields of type A ->
-- f A for various As. Projector is the type of the
-- projection functions of plates.
type Projector p a = forall f. p f -> a -> f a
-- | A Multiplate is a constructor of kind (* -> *) ->
-- * operating on Applicative functors having functions
-- multiplate and mkPlate that satisfy the following two
-- laws:
--
-- multiplate purePlate = purePlate where -- purePlate = mkPlate (\_ -> pure)
multiplate (composePlate p1 p2) = -- composePlate (multiplate p1) (multiplate p2) -- where composePlate p1 p2 = mkPlate (\proj a -> -- (Compose (proj p1 `fmap` proj p2 a)))
-- multiplate (mkPlate (\_ -> Identity)) = mkPlate (\_ -> Identity) --class Multiplate p multiplate :: (Multiplate p, Applicative f) => p f -> p f mkPlate :: Multiplate p => (forall a. Projector p a -> (a -> f a)) -> p f -- | Given a natural transformation between two functors, f and -- g, and a plate over f, compose the natural -- transformation with each field of the plate. applyNaturalTransform :: Multiplate p => (forall a. f a -> g a) -> p f -> p g -- | Given an Applicative f, purePlate builds a -- plate over f whose fields are all pure. -- -- Generally purePlate is used as the base of a record update. One -- constructs the expression -- --
-- purePlate { fieldOfInterest = \a -> case a of
-- | constructorOfInterest -> expr
-- | _ -> pure a
-- }
--
--
-- and this is a typical parameter that is passed to most functions in
-- this library.
purePlate :: (Multiplate p, Applicative f) => p f
-- | Given an Alternative f, emptyPlate builds a
-- plate over f whose fields are all const
-- empty.
--
-- Generally emptyPlate is used as the base of a record update.
-- One constructs the expression
--
--
-- emptyPlate { fieldOfInterest = \a -> case a of
-- | constructorOfInterest -> expr
-- | _ -> empty
-- }
--
--
-- and this is a typical parameter that is passed to evalFamily
-- and evalFamilyM.
emptyPlate :: (Multiplate p, Alternative f) => p f
-- | Given two plates over a monad m, the fields of the plate can
-- be Kleisli composed (<=<) fieldwise.
kleisliComposePlate :: (Multiplate p, Monad m) => p m -> p m -> p m
-- | Given two plates, they can be composed fieldwise yielding the
-- composite functor.
composePlate :: (Multiplate p, Functor g) => p f -> p g -> p (Compose g f)
-- | Given two plates with one over the Identity functor, the two
-- plates can be composed fieldwise.
composePlateRightId :: Multiplate p => p f -> p Identity -> p f
-- | Given two plates with one over the Identity functor, the two
-- plates can be composed fieldwise.
composePlateLeftId :: (Multiplate p, Functor f) => p Identity -> p f -> p f
-- | Given two plates with one over the Constant o
-- applicative functor for a Monoid o, each field of the
-- plate can be pointwise appended with mappend.
appendPlate :: (Multiplate p, Monoid o) => p (Constant o) -> p (Constant o) -> p (Constant o)
-- | Given a plate whose fields all return a Monoid o,
-- mChildren produces a plate that returns the mconcat of
-- all the children of the input.
mChildren :: (Multiplate p, Monoid o) => p (Constant o) -> p (Constant o)
-- | Given a plate whose fields all return a Monoid o,
-- preorderFold produces a plate that returns the mconcat
-- of the family of the input. The input itself produces the leftmost
-- element of the concatenation, then this is followed by the family of
-- the first child, then it is followed by the family of the second
-- child, and so forth.
preorderFold :: (Multiplate p, Monoid o) => p (Constant o) -> p (Constant o)
-- | Given a plate whose fields all return a Monoid o,
-- preorderFold produces a plate that returns the mconcat
-- of the family of the input. The concatenation sequence begins with the
-- family of the first child, then it is followed by the family of the
-- second child, and so forth until finally the input itself produces the
-- rightmost element of the concatenation.
postorderFold :: (Multiplate p, Monoid o) => p (Constant o) -> p (Constant o)
-- | Given a plate whose fields transform each type, mapChildren
-- returns a plate whose fields transform the children of the input.
mapChildren :: Multiplate p => p Identity -> p Identity
-- | Given a plate whose fields transform each type, mapFamily
-- returns a plate whose fields transform the family of the input. The
-- traversal proceeds bottom up, first transforming the families of the
-- children, before finally transforming the value itself.
mapFamily :: Multiplate p => p Identity -> p Identity
-- | Given a plate whose fields transform each type, mapChildrenM
-- returns a plate whose fields transform the children of the input. The
-- processing is sequenced from the first child to the last child.
mapChildrenM :: (Multiplate p, Applicative m, Monad m) => p m -> p m
-- | Given a plate whose fields transform each type, mapFamilyM
-- returns a plate whose fields transform the family of the input. The
-- sequencing is done in a depth-first postorder traversal.
mapFamilyM :: (Multiplate p, Applicative m, Monad m) => p m -> p m
-- | Given a plate whose fields maybe transforms each type,
-- evalFamily returns a plate whose fields exhaustively transform
-- the family of the input. The traversal proceeds bottom up, first
-- transforming the families of the children. If a transformation
-- succeeds then the result is re-evalFamilyed.
--
-- A post-condition is that the input transform returns Nothing on
-- all family members of the output, or more formally
--
-- -- preorderFold (applyNaturalTransform t f) `composePlate` (evalFamily f) ⊑ purePlate -- where -- t :: forall a. Maybe a -> Constant All a -- t = Constant . All . isNothing --evalFamily :: Multiplate p => p Maybe -> p Identity -- | Given a plate whose fields maybe transforms each type, -- evalFamilyM returns a plate whose fields exhaustively transform -- the family of the input. The sequencing is done in a depth-first -- postorder traversal, but if a transformation succeeds then the result -- is re-evalFamilyMed. evalFamilyM :: (Multiplate p, Applicative m, Monad m) => p (MaybeT m) -> p m -- | Given a plate used for evalFamily, replace returning -- Nothing with returning the input. This transforms plates -- suitable for evalFamily into plates suitable form -- mapFamily. always :: Multiplate p => p Maybe -> p Identity -- | Given a plate used for evalFamilyM, replace returning -- Nothing with returning the input. This transforms plates -- suitable for evalFamilyM into plates suitable form -- mapFamilyM. alwaysM :: (Multiplate p, Functor f) => p (MaybeT f) -> p f -- | Given a projection function for a plate over the Identity -- functor, upgrade the projection function to strip off the wrapper. traverseFor :: Multiplate p => Projector p a -> p Identity -> a -> a -- | Instantiate a projection function at a monad. traverseMFor :: (Multiplate p, Monad m) => Projector p a -> p m -> a -> m a -- | Given a projection function for a plate over the Constant -- o functor, upgrade the projection function to strip off the -- wrapper. foldFor :: Multiplate p => Projector p a -> p (Constant o) -> a -> o -- | Given a projection function for a plate over the Constant -- o functor, and a continuation for o, upgrade the -- projection function to strip off the wrapper and run the continuation. -- -- Typically the continuation simply strips off a wrapper for o. unwrapFor :: Multiplate p => (o -> b) -> Projector p a -> p (Constant o) -> a -> b -- | Given a projection function for a plate over the Constant -- (Sum n) functor, upgrade the projection function to strip -- off the wrappers. sumFor :: Multiplate p => Projector p a -> p (Constant (Sum n)) -> a -> n -- | Given a projection function for a plate over the Constant -- (Product n) functor, upgrade the projection function to -- strip off the wrappers. productFor :: Multiplate p => Projector p a -> p (Constant (Product n)) -> a -> n -- | Given a projection function for a plate over the Constant -- All functor, upgrade the projection function to strip off -- the wrappers. allFor :: Multiplate p => Projector p a -> p (Constant All) -> a -> Bool -- | Given a projection function for a plate over the Constant -- Any functor, upgrade the projection function to strip off -- the wrappers. anyFor :: Multiplate p => Projector p a -> p (Constant Any) -> a -> Bool -- | Given a projection function for a plate over the Constant -- (First n) functor, upgrade the projection function to -- strip off the wrappers. firstFor :: Multiplate p => Projector p a -> p (Constant (First b)) -> a -> Maybe b -- | Given a projection function for a plate over the Constant -- (Last n) functor, upgrade the projection function to strip -- off the wrappers. lastFor :: Multiplate p => Projector p a -> p (Constant (Last b)) -> a -> Maybe b