{-# LANGUAGE CPP #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}

#ifdef TRUSTWORTHY
{-# LANGUAGE Trustworthy #-} -- template-haskell
#endif

#include "lens-common.h"

-------------------------------------------------------------------------------
-- |
-- Module      :  Control.Lens.Plated
-- Copyright   :  (C) 2012-16 Edward Kmett
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
-- Stability   :  provisional
-- Portability :  Rank2Types
--
-- The name \"plate\" stems originally from \"boilerplate\", which was the term
-- used by the \"Scrap Your Boilerplate\" papers, and later inherited by Neil
-- Mitchell's \"Uniplate\".
--
-- <https://www.cs.york.ac.uk/fp/darcs/uniplate/uniplate.htm>
--
-- The combinators in here are designed to be compatible with and subsume the
-- @uniplate@ API with the notion of a 'Traversal' replacing
-- a 'Data.Data.Lens.uniplate' or 'Data.Data.Lens.biplate'.
--
-- By implementing these combinators in terms of 'plate' instead of
-- 'Data.Data.Lens.uniplate' additional type safety is gained, as the user is
-- no longer responsible for maintaining invariants such as the number of
-- children they received.
--
-- Note: The @Biplate@ is /deliberately/ excluded from the API here, with the
-- intention that you replace them with either explicit traversals, or by using the
-- @On@ variants of the combinators below with 'Data.Data.Lens.biplate' from
-- @Data.Data.Lens@. As a design, it forced the user into too many situations where
-- they had to choose between correctness and ease of use, and it was brittle in the
-- face of competing imports.
--
-- The sensible use of these combinators makes some simple assumptions.  Notably, any
-- of the @On@ combinators are expecting a 'Traversal', 'Setter' or 'Fold'
-- to play the role of the 'Data.Data.Lens.biplate' combinator, and so when the
-- types of the contents and the container match, they should be the 'id' 'Traversal',
-- 'Setter' or 'Fold'.
--
-- It is often beneficial to use the combinators in this module with the combinators
-- from @Data.Data.Lens@ or @GHC.Generics.Lens@ to make it easier to automatically
-- derive definitions for 'plate', or to derive custom traversals.
-------------------------------------------------------------------------------
module Control.Lens.Plated
  (
  -- * Uniplate
    Plated(..)

  -- * Uniplate Combinators
  , children
  , rewrite, rewriteOf, rewriteOn, rewriteOnOf
  , rewriteM, rewriteMOf, rewriteMOn, rewriteMOnOf
  , universe, universeOf, universeOn, universeOnOf
  , cosmos, cosmosOf, cosmosOn, cosmosOnOf
  , transform, transformOf, transformOn, transformOnOf
  , transformM, transformMOf, transformMOn, transformMOnOf
  , contexts, contextsOf, contextsOn, contextsOnOf
  , holes, holesOn, holesOnOf
  , para, paraOf
  , (...), deep

  -- * Compos
  -- $compos
  , composOpFold

  -- * Parts
  , parts

  -- * Generics
  , gplate
  , gplate1
  , GPlated
  , GPlated1
  )
  where

import Prelude ()

import Control.Comonad.Cofree
import qualified Control.Comonad.Trans.Cofree as CoTrans
import Control.Lens.Fold
import Control.Lens.Getter
import Control.Lens.Indexed
import Control.Lens.Internal.Context
import Control.Lens.Internal.Prelude
import Control.Lens.Type
import Control.Lens.Setter
import Control.Lens.Traversal
import Control.Monad.Free as Monad
import Control.Monad.Free.Church as Church
import Control.Monad.Trans.Free as Trans
import qualified Language.Haskell.TH as TH
import Data.Data
import Data.Data.Lens
import Data.Tree
import GHC.Generics

-- $setup
-- >>> :set -XDeriveGeneric -XDeriveDataTypeable
-- >>> import Control.Applicative
-- >>> import Data.Data (Data)
-- >>> import GHC.Generics (Generic)
-- >>> import Control.Lens

-- | A 'Plated' type is one where we know how to extract its immediate self-similar children.
--
-- /Example 1/:
--
-- @
-- import Control.Applicative
-- import Control.Lens
-- import Control.Lens.Plated
-- import Data.Data
-- import Data.Data.Lens ('Data.Data.Lens.uniplate')
-- @
--
-- @
-- data Expr
--   = Val 'Int'
--   | Neg Expr
--   | Add Expr Expr
--   deriving ('Eq','Ord','Show','Read','Data')
-- @
--
-- @
-- instance 'Plated' Expr where
--   'plate' f (Neg e) = Neg '<$>' f e
--   'plate' f (Add a b) = Add '<$>' f a '<*>' f b
--   'plate' _ a = 'pure' a
-- @
--
-- /or/
--
-- @
-- instance 'Plated' Expr where
--   'plate' = 'Data.Data.Lens.uniplate'
-- @
--
-- /Example 2/:
--
-- @
-- import Control.Applicative
-- import Control.Lens
-- import Control.Lens.Plated
-- import Data.Data
-- import Data.Data.Lens ('Data.Data.Lens.uniplate')
-- @
--
-- @
-- data Tree a
--   = Bin (Tree a) (Tree a)
--   | Tip a
--   deriving ('Eq','Ord','Show','Read','Data')
-- @
--
-- @
-- instance 'Plated' (Tree a) where
--   'plate' f (Bin l r) = Bin '<$>' f l '<*>' f r
--   'plate' _ t = 'pure' t
-- @
--
-- /or/
--
-- @
-- instance 'Data' a => 'Plated' (Tree a) where
--   'plate' = 'uniplate'
-- @
--
-- Note the big distinction between these two implementations.
--
-- The former will only treat children directly in this tree as descendents,
-- the latter will treat trees contained in the values under the tips also
-- as descendants!
--
-- When in doubt, pick a 'Traversal' and just use the various @...Of@ combinators
-- rather than pollute 'Plated' with orphan instances!
--
-- If you want to find something unplated and non-recursive with 'Data.Data.Lens.biplate'
-- use the @...OnOf@ variant with 'ignored', though those usecases are much better served
-- in most cases by using the existing 'Lens' combinators! e.g.
--
-- @
-- 'toListOf' 'biplate' ≡ 'universeOnOf' 'biplate' 'ignored'
-- @
--
-- This same ability to explicitly pass the 'Traversal' in question is why there is no
-- analogue to uniplate's @Biplate@.
--
-- Moreover, since we can allow custom traversals, we implement reasonable defaults for
-- polymorphic data types, that only 'Control.Traversable.traverse' into themselves, and /not/ their
-- polymorphic arguments.

class Plated a where
  -- | 'Traversal' of the immediate children of this structure.
  --
  -- If you're using GHC 7.2 or newer and your type has a 'Data' instance,
  -- 'plate' will default to 'uniplate' and you can choose to not override
  -- it with your own definition.
  plate :: Traversal' a a
  default plate :: Data a => Traversal' a a
  plate = forall a. Data a => Traversal' a a
uniplate

instance Plated [a] where
  plate :: Traversal' [a] [a]
plate [a] -> f [a]
f (a
x:[a]
xs) = (a
xforall a. a -> [a] -> [a]
:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a] -> f [a]
f [a]
xs
  plate [a] -> f [a]
_ [] = forall (f :: * -> *) a. Applicative f => a -> f a
pure []

instance Traversable f => Plated (Monad.Free f a) where
  plate :: Traversal' (Free f a) (Free f a)
plate Free f a -> f (Free f a)
f (Monad.Free f (Free f a)
as) = forall (f :: * -> *) a. f (Free f a) -> Free f a
Monad.Free forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Free f a -> f (Free f a)
f f (Free f a)
as
  plate Free f a -> f (Free f a)
_ Free f a
x         = forall (f :: * -> *) a. Applicative f => a -> f a
pure Free f a
x

instance (Traversable f, Traversable m) => Plated (Trans.FreeT f m a) where
  plate :: Traversal' (FreeT f m a) (FreeT f m a)
plate FreeT f m a -> f (FreeT f m a)
f (Trans.FreeT m (FreeF f a (FreeT f m a))
xs) = forall (f :: * -> *) (m :: * -> *) a.
m (FreeF f a (FreeT f m a)) -> FreeT f m a
Trans.FreeT forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse FreeT f m a -> f (FreeT f m a)
f) m (FreeF f a (FreeT f m a))
xs

instance Traversable f => Plated (Church.F f a) where
  plate :: Traversal' (F f a) (F f a)
plate F f a -> f (F f a)
f = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (f :: * -> *) a. Functor f => Free f a -> F f a
Church.toF forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Plated a => Traversal' a a
plate (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (f :: * -> *) (m :: * -> *) a. MonadFree f m => F f a -> m a
Church.fromF forall b c a. (b -> c) -> (a -> b) -> a -> c
. F f a -> f (F f a)
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a. Functor f => Free f a -> F f a
Church.toF) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) (m :: * -> *) a. MonadFree f m => F f a -> m a
Church.fromF

-- -- This one can't work
--
-- instance (Traversable f, Traversable m) => Plated (ChurchT.FT f m a) where
--   plate f = fmap ChurchT.toFT . plate (fmap ChurchT.fromFT . f . ChurchT.toFT) . ChurchT.fromFT

instance (Traversable f, Traversable w) => Plated (CoTrans.CofreeT f w a) where
  plate :: Traversal' (CofreeT f w a) (CofreeT f w a)
plate CofreeT f w a -> f (CofreeT f w a)
f (CoTrans.CofreeT w (CofreeF f a (CofreeT f w a))
xs) = forall (f :: * -> *) (w :: * -> *) a.
w (CofreeF f a (CofreeT f w a)) -> CofreeT f w a
CoTrans.CofreeT forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse CofreeT f w a -> f (CofreeT f w a)
f) w (CofreeF f a (CofreeT f w a))
xs

instance Traversable f => Plated (Cofree f a) where
  plate :: Traversal' (Cofree f a) (Cofree f a)
plate Cofree f a -> f (Cofree f a)
f (a
a :< f (Cofree f a)
as) = forall (f :: * -> *) a. a -> f (Cofree f a) -> Cofree f a
(:<) a
a forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Cofree f a -> f (Cofree f a)
f f (Cofree f a)
as

instance Plated (Tree a) where
  plate :: Traversal' (Tree a) (Tree a)
plate Tree a -> f (Tree a)
f (Node a
a [Tree a]
as) = forall a. a -> [Tree a] -> Tree a
Node a
a forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Tree a -> f (Tree a)
f [Tree a]
as

{- Default uniplate instances -}
instance Plated TH.Exp
instance Plated TH.Dec
instance Plated TH.Con
instance Plated TH.Type
instance Plated TH.Stmt
instance Plated TH.Pat


infixr 9 ...
-- | Compose through a plate
(...) :: (Applicative f, Plated c) => LensLike f s t c c -> Over p f c c a b -> Over p f s t a b
LensLike f s t c c
l ... :: forall {k} (f :: * -> *) c s t (p :: k -> * -> *) (a :: k) b.
(Applicative f, Plated c) =>
LensLike f s t c c -> Over p f c c a b -> Over p f s t a b
... Over p f c c a b
m = LensLike f s t c c
l forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Plated a => Traversal' a a
plate forall b c a. (b -> c) -> (a -> b) -> a -> c
. Over p f c c a b
m
{-# INLINE (...) #-}


-- | Try to apply a traversal to all transitive descendants of a 'Plated' container, but
-- do not recurse through matching descendants.
--
-- @
-- 'deep' :: 'Plated' s => 'Fold' s a                 -> 'Fold' s a
-- 'deep' :: 'Plated' s => 'IndexedFold' s a          -> 'IndexedFold' s a
-- 'deep' :: 'Plated' s => 'Traversal' s s a b        -> 'Traversal' s s a b
-- 'deep' :: 'Plated' s => 'IndexedTraversal' s s a b -> 'IndexedTraversal' s s a b
-- @
deep :: (Conjoined p, Applicative f, Plated s) => Traversing p f s s a b -> Over p f s s a b
deep :: forall (p :: * -> * -> *) (f :: * -> *) s a b.
(Conjoined p, Applicative f, Plated s) =>
Traversing p f s s a b -> Over p f s s a b
deep = forall (p :: * -> * -> *) (f :: * -> *) s t a b.
(Conjoined p, Applicative f) =>
LensLike f s t s t -> Traversing p f s t a b -> Over p f s t a b
deepOf forall a. Plated a => Traversal' a a
plate

-------------------------------------------------------------------------------
-- Children
-------------------------------------------------------------------------------

-- | Extract the immediate descendants of a 'Plated' container.
--
-- @
-- 'children' ≡ 'toListOf' 'plate'
-- @
children :: Plated a => a -> [a]
children :: forall a. Plated a => a -> [a]
children = forall a s. Getting (Endo [a]) s a -> s -> [a]
toListOf forall a. Plated a => Traversal' a a
plate
{-# INLINE children #-}

-------------------------------------------------------------------------------
-- Rewriting
-------------------------------------------------------------------------------

-- | Rewrite by applying a rule everywhere you can. Ensures that the rule cannot
-- be applied anywhere in the result:
--
-- @
-- propRewrite r x = 'all' ('Data.Just.isNothing' '.' r) ('universe' ('rewrite' r x))
-- @
--
-- Usually 'transform' is more appropriate, but 'rewrite' can give better
-- compositionality. Given two single transformations @f@ and @g@, you can
-- construct @\\a -> f a '<|>' g a@ which performs both rewrites until a fixed point.
rewrite :: Plated a => (a -> Maybe a) -> a -> a
rewrite :: forall a. Plated a => (a -> Maybe a) -> a -> a
rewrite = forall a b. ASetter a b a b -> (b -> Maybe a) -> a -> b
rewriteOf forall a. Plated a => Traversal' a a
plate
{-# INLINE rewrite #-}

-- | Rewrite by applying a rule everywhere you can. Ensures that the rule cannot
-- be applied anywhere in the result:
--
-- @
-- propRewriteOf l r x = 'all' ('Data.Just.isNothing' '.' r) ('universeOf' l ('rewriteOf' l r x))
-- @
--
-- Usually 'transformOf' is more appropriate, but 'rewriteOf' can give better
-- compositionality. Given two single transformations @f@ and @g@, you can
-- construct @\\a -> f a '<|>' g a@ which performs both rewrites until a fixed point.
--
-- @
-- 'rewriteOf' :: 'Control.Lens.Iso.Iso'' a a       -> (a -> 'Maybe' a) -> a -> a
-- 'rewriteOf' :: 'Lens'' a a      -> (a -> 'Maybe' a) -> a -> a
-- 'rewriteOf' :: 'Traversal'' a a -> (a -> 'Maybe' a) -> a -> a
-- 'rewriteOf' :: 'Setter'' a a    -> (a -> 'Maybe' a) -> a -> a
-- @
rewriteOf :: ASetter a b a b -> (b -> Maybe a) -> a -> b
rewriteOf :: forall a b. ASetter a b a b -> (b -> Maybe a) -> a -> b
rewriteOf ASetter a b a b
l b -> Maybe a
f = a -> b
go where
  go :: a -> b
go = forall a b. ASetter a b a b -> (b -> b) -> a -> b
transformOf ASetter a b a b
l (\b
x -> forall b a. b -> (a -> b) -> Maybe a -> b
maybe b
x a -> b
go (b -> Maybe a
f b
x))
{-# INLINE rewriteOf #-}

-- | Rewrite recursively over part of a larger structure.
--
-- @
-- 'rewriteOn' :: 'Plated' a => 'Control.Lens.Iso.Iso'' s a       -> (a -> 'Maybe' a) -> s -> s
-- 'rewriteOn' :: 'Plated' a => 'Lens'' s a      -> (a -> 'Maybe' a) -> s -> s
-- 'rewriteOn' :: 'Plated' a => 'Traversal'' s a -> (a -> 'Maybe' a) -> s -> s
-- 'rewriteOn' :: 'Plated' a => 'ASetter'' s a   -> (a -> 'Maybe' a) -> s -> s
-- @
rewriteOn :: Plated a => ASetter s t a a -> (a -> Maybe a) -> s -> t
rewriteOn :: forall a s t.
Plated a =>
ASetter s t a a -> (a -> Maybe a) -> s -> t
rewriteOn ASetter s t a a
b = forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter s t a a
b forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Plated a => (a -> Maybe a) -> a -> a
rewrite
{-# INLINE rewriteOn #-}

-- | Rewrite recursively over part of a larger structure using a specified 'Setter'.
--
-- @
-- 'rewriteOnOf' :: 'Control.Lens.Iso.Iso'' s a       -> 'Control.Lens.Iso.Iso'' a a       -> (a -> 'Maybe' a) -> s -> s
-- 'rewriteOnOf' :: 'Lens'' s a      -> 'Lens'' a a      -> (a -> 'Maybe' a) -> s -> s
-- 'rewriteOnOf' :: 'Traversal'' s a -> 'Traversal'' a a -> (a -> 'Maybe' a) -> s -> s
-- 'rewriteOnOf' :: 'Setter'' s a    -> 'Setter'' a a    -> (a -> 'Maybe' a) -> s -> s
-- @
rewriteOnOf :: ASetter s t a b -> ASetter a b a b -> (b -> Maybe a) -> s -> t
rewriteOnOf :: forall s t a b.
ASetter s t a b -> ASetter a b a b -> (b -> Maybe a) -> s -> t
rewriteOnOf ASetter s t a b
b ASetter a b a b
l = forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter s t a b
b forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. ASetter a b a b -> (b -> Maybe a) -> a -> b
rewriteOf ASetter a b a b
l
{-# INLINE rewriteOnOf #-}

-- | Rewrite by applying a monadic rule everywhere you can. Ensures that the rule cannot
-- be applied anywhere in the result.
rewriteM :: (Monad m, Plated a) => (a -> m (Maybe a)) -> a -> m a
rewriteM :: forall (m :: * -> *) a.
(Monad m, Plated a) =>
(a -> m (Maybe a)) -> a -> m a
rewriteM = forall (m :: * -> *) a b.
Monad m =>
LensLike (WrappedMonad m) a b a b -> (b -> m (Maybe a)) -> a -> m b
rewriteMOf forall a. Plated a => Traversal' a a
plate
{-# INLINE rewriteM #-}

-- | Rewrite by applying a monadic rule everywhere you recursing with a user-specified 'Traversal'.
-- Ensures that the rule cannot be applied anywhere in the result.
rewriteMOf :: Monad m => LensLike (WrappedMonad m) a b a b -> (b -> m (Maybe a)) -> a -> m b
rewriteMOf :: forall (m :: * -> *) a b.
Monad m =>
LensLike (WrappedMonad m) a b a b -> (b -> m (Maybe a)) -> a -> m b
rewriteMOf LensLike (WrappedMonad m) a b a b
l b -> m (Maybe a)
f = a -> m b
go where
  go :: a -> m b
go = forall (m :: * -> *) a b.
Monad m =>
LensLike (WrappedMonad m) a b a b -> (b -> m b) -> a -> m b
transformMOf LensLike (WrappedMonad m) a b a b
l (\b
x -> b -> m (Maybe a)
f b
x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. Monad m => a -> m a
return b
x) a -> m b
go)
{-# INLINE rewriteMOf #-}

-- | Rewrite by applying a monadic rule everywhere inside of a structure located by a user-specified 'Traversal'.
-- Ensures that the rule cannot be applied anywhere in the result.
rewriteMOn :: (Monad m, Plated a) => LensLike (WrappedMonad m) s t a a -> (a -> m (Maybe a)) -> s -> m t
rewriteMOn :: forall (m :: * -> *) a s t.
(Monad m, Plated a) =>
LensLike (WrappedMonad m) s t a a -> (a -> m (Maybe a)) -> s -> m t
rewriteMOn LensLike (WrappedMonad m) s t a a
b = forall (m :: * -> *) s t a b.
LensLike (WrappedMonad m) s t a b -> (a -> m b) -> s -> m t
mapMOf LensLike (WrappedMonad m) s t a a
b forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a.
(Monad m, Plated a) =>
(a -> m (Maybe a)) -> a -> m a
rewriteM
{-# INLINE rewriteMOn #-}

-- | Rewrite by applying a monadic rule everywhere inside of a structure located by a user-specified 'Traversal',
-- using a user-specified 'Traversal' for recursion. Ensures that the rule cannot be applied anywhere in the result.
rewriteMOnOf :: Monad m => LensLike (WrappedMonad m) s t a b -> LensLike (WrappedMonad m) a b a b -> (b -> m (Maybe a)) -> s -> m t
rewriteMOnOf :: forall (m :: * -> *) s t a b.
Monad m =>
LensLike (WrappedMonad m) s t a b
-> LensLike (WrappedMonad m) a b a b
-> (b -> m (Maybe a))
-> s
-> m t
rewriteMOnOf LensLike (WrappedMonad m) s t a b
b LensLike (WrappedMonad m) a b a b
l = forall (m :: * -> *) s t a b.
LensLike (WrappedMonad m) s t a b -> (a -> m b) -> s -> m t
mapMOf LensLike (WrappedMonad m) s t a b
b forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a b.
Monad m =>
LensLike (WrappedMonad m) a b a b -> (b -> m (Maybe a)) -> a -> m b
rewriteMOf LensLike (WrappedMonad m) a b a b
l
{-# INLINE rewriteMOnOf #-}

-------------------------------------------------------------------------------
-- Universe
-------------------------------------------------------------------------------

-- | Retrieve all of the transitive descendants of a 'Plated' container, including itself.
universe :: Plated a => a -> [a]
universe :: forall a. Plated a => a -> [a]
universe = forall a. Getting (Endo [a]) a a -> a -> [a]
universeOf forall a. Plated a => Traversal' a a
plate
{-# INLINE universe #-}

-- | Given a 'Fold' that knows how to locate immediate children, retrieve all of the transitive descendants of a node, including itself.
--
-- @
-- 'universeOf' :: 'Fold' a a -> a -> [a]
-- @
universeOf :: Getting (Endo [a]) a a -> a -> [a]
universeOf :: forall a. Getting (Endo [a]) a a -> a -> [a]
universeOf Getting (Endo [a]) a a
l = \a
x -> forall a. Endo a -> a -> a
appEndo (forall a. Getting (Endo [a]) a a -> a -> Endo [a]
universeOf' Getting (Endo [a]) a a
l a
x) []
{-# INLINE universeOf #-}

universeOf' :: Getting (Endo [a]) a a -> a -> Endo [a]
universeOf' :: forall a. Getting (Endo [a]) a a -> a -> Endo [a]
universeOf' Getting (Endo [a]) a a
l = a -> Endo [a]
go where
  go :: a -> Endo [a]
go a
a = forall a. (a -> a) -> Endo a
Endo (a
a forall a. a -> [a] -> [a]
:) forall a. Semigroup a => a -> a -> a
<> forall r s a. Getting r s a -> (a -> r) -> s -> r
foldMapOf Getting (Endo [a]) a a
l a -> Endo [a]
go a
a
{-# INLINE universeOf' #-}


-- | Given a 'Fold' that knows how to find 'Plated' parts of a container retrieve them and all of their descendants, recursively.
universeOn ::  Plated a => Getting (Endo [a]) s a -> s -> [a]
universeOn :: forall a s. Plated a => Getting (Endo [a]) s a -> s -> [a]
universeOn Getting (Endo [a]) s a
b = forall a s.
Getting (Endo [a]) s a -> Getting (Endo [a]) a a -> s -> [a]
universeOnOf Getting (Endo [a]) s a
b forall a. Plated a => Traversal' a a
plate
{-# INLINE universeOn #-}

-- | Given a 'Fold' that knows how to locate immediate children, retrieve all of the transitive descendants of a node, including itself that lie
-- in a region indicated by another 'Fold'.
--
-- @
-- 'toListOf' l ≡ 'universeOnOf' l 'ignored'
-- @
universeOnOf :: Getting (Endo [a]) s a -> Getting (Endo [a]) a a -> s -> [a]
universeOnOf :: forall a s.
Getting (Endo [a]) s a -> Getting (Endo [a]) a a -> s -> [a]
universeOnOf Getting (Endo [a]) s a
b = \Getting (Endo [a]) a a
p s
x -> forall a. Endo a -> a -> a
appEndo (forall r s a. Getting r s a -> (a -> r) -> s -> r
foldMapOf Getting (Endo [a]) s a
b (forall a. Getting (Endo [a]) a a -> a -> Endo [a]
universeOf' Getting (Endo [a]) a a
p) s
x) []
{-# INLINE universeOnOf #-}

-- | Fold over all transitive descendants of a 'Plated' container, including itself.
cosmos :: Plated a => Fold a a
cosmos :: forall a. Plated a => Fold a a
cosmos = forall (f :: * -> *) a.
(Applicative f, Contravariant f) =>
LensLike' f a a -> LensLike' f a a
cosmosOf forall a. Plated a => Traversal' a a
plate
{-# INLINE cosmos #-}

-- | Given a 'Fold' that knows how to locate immediate children, fold all of the transitive descendants of a node, including itself.
--
-- @
-- 'cosmosOf' :: 'Fold' a a -> 'Fold' a a
-- @
cosmosOf :: (Applicative f, Contravariant f) => LensLike' f a a -> LensLike' f a a
-- The 'Contravariant' constraint isn't required for the implementation. Since any 'Traversal' produced with 'cosmosOf' is more likely than
-- not to be broken, the additional constraint serves to restrict 'cosmosOf' to 'Fold's.
cosmosOf :: forall (f :: * -> *) a.
(Applicative f, Contravariant f) =>
LensLike' f a a -> LensLike' f a a
cosmosOf LensLike' f a a
d a -> f a
f a
s = a -> f a
f a
s forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> LensLike' f a a
d (forall (f :: * -> *) a.
(Applicative f, Contravariant f) =>
LensLike' f a a -> LensLike' f a a
cosmosOf LensLike' f a a
d a -> f a
f) a
s
{-# INLINE cosmosOf #-}

-- | Given a 'Fold' that knows how to find 'Plated' parts of a container fold them and all of their descendants, recursively.
--
-- @
-- 'cosmosOn' :: 'Plated' a => 'Fold' s a -> 'Fold' s a
-- @
cosmosOn :: (Applicative f, Contravariant f, Plated a) => LensLike' f s a -> LensLike' f s a
cosmosOn :: forall (f :: * -> *) a s.
(Applicative f, Contravariant f, Plated a) =>
LensLike' f s a -> LensLike' f s a
cosmosOn LensLike' f s a
d = forall (f :: * -> *) s a.
(Applicative f, Contravariant f) =>
LensLike' f s a -> LensLike' f a a -> LensLike' f s a
cosmosOnOf LensLike' f s a
d forall a. Plated a => Traversal' a a
plate
{-# INLINE cosmosOn #-}

-- | Given a 'Fold' that knows how to locate immediate children, fold all of the transitive descendants of a node, including itself that lie
-- in a region indicated by another 'Fold'.
--
-- @
-- 'cosmosOnOf' :: 'Fold' s a -> 'Fold' a a -> 'Fold' s a
-- @
cosmosOnOf :: (Applicative f, Contravariant f) => LensLike' f s a -> LensLike' f a a -> LensLike' f s a
cosmosOnOf :: forall (f :: * -> *) s a.
(Applicative f, Contravariant f) =>
LensLike' f s a -> LensLike' f a a -> LensLike' f s a
cosmosOnOf LensLike' f s a
d LensLike' f a a
p = LensLike' f s a
d forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a.
(Applicative f, Contravariant f) =>
LensLike' f a a -> LensLike' f a a
cosmosOf LensLike' f a a
p
{-# INLINE cosmosOnOf #-}

-------------------------------------------------------------------------------
-- Transformation
-------------------------------------------------------------------------------

-- | Transform every element in the tree, in a bottom-up manner.
--
-- For example, replacing negative literals with literals:
--
-- @
-- negLits = 'transform' $ \\x -> case x of
--   Neg (Lit i) -> Lit ('negate' i)
--   _           -> x
-- @
transform :: Plated a => (a -> a) -> a -> a
transform :: forall a. Plated a => (a -> a) -> a -> a
transform = forall a b. ASetter a b a b -> (b -> b) -> a -> b
transformOf forall a. Plated a => Traversal' a a
plate
{-# INLINE transform #-}

-- | Transform every element in the tree in a bottom-up manner over a region indicated by a 'Setter'.
--
-- @
-- 'transformOn' :: 'Plated' a => 'Traversal'' s a -> (a -> a) -> s -> s
-- 'transformOn' :: 'Plated' a => 'Setter'' s a    -> (a -> a) -> s -> s
-- @
transformOn :: Plated a => ASetter s t a a -> (a -> a) -> s -> t
transformOn :: forall a s t. Plated a => ASetter s t a a -> (a -> a) -> s -> t
transformOn ASetter s t a a
b = forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter s t a a
b forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Plated a => (a -> a) -> a -> a
transform
{-# INLINE transformOn #-}

-- | Transform every element by recursively applying a given 'Setter' in a bottom-up manner.
--
-- @
-- 'transformOf' :: 'Traversal'' a a -> (a -> a) -> a -> a
-- 'transformOf' :: 'Setter'' a a    -> (a -> a) -> a -> a
-- @
transformOf :: ASetter a b a b -> (b -> b) -> a -> b
transformOf :: forall a b. ASetter a b a b -> (b -> b) -> a -> b
transformOf ASetter a b a b
l b -> b
f = a -> b
go where
  go :: a -> b
go = b -> b
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter a b a b
l a -> b
go
{-# INLINE transformOf #-}

-- | Transform every element in a region indicated by a 'Setter' by recursively applying another 'Setter'
-- in a bottom-up manner.
--
-- @
-- 'transformOnOf' :: 'Setter'' s a -> 'Traversal'' a a -> (a -> a) -> s -> s
-- 'transformOnOf' :: 'Setter'' s a -> 'Setter'' a a    -> (a -> a) -> s -> s
-- @
transformOnOf :: ASetter s t a b -> ASetter a b a b -> (b -> b) -> s -> t
transformOnOf :: forall s t a b.
ASetter s t a b -> ASetter a b a b -> (b -> b) -> s -> t
transformOnOf ASetter s t a b
b ASetter a b a b
l = forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter s t a b
b forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. ASetter a b a b -> (b -> b) -> a -> b
transformOf ASetter a b a b
l
{-# INLINE transformOnOf #-}

-- | Transform every element in the tree, in a bottom-up manner, monadically.
transformM :: (Monad m, Plated a) => (a -> m a) -> a -> m a
transformM :: forall (m :: * -> *) a.
(Monad m, Plated a) =>
(a -> m a) -> a -> m a
transformM = forall (m :: * -> *) a b.
Monad m =>
LensLike (WrappedMonad m) a b a b -> (b -> m b) -> a -> m b
transformMOf forall a. Plated a => Traversal' a a
plate
{-# INLINE transformM #-}

-- | Transform every element in the tree in a region indicated by a supplied 'Traversal', in a bottom-up manner, monadically.
--
-- @
-- 'transformMOn' :: ('Monad' m, 'Plated' a) => 'Traversal'' s a -> (a -> m a) -> s -> m s
-- @
transformMOn :: (Monad m, Plated a) => LensLike (WrappedMonad m) s t a a -> (a -> m a) -> s -> m t
transformMOn :: forall (m :: * -> *) a s t.
(Monad m, Plated a) =>
LensLike (WrappedMonad m) s t a a -> (a -> m a) -> s -> m t
transformMOn LensLike (WrappedMonad m) s t a a
b = forall (m :: * -> *) s t a b.
LensLike (WrappedMonad m) s t a b -> (a -> m b) -> s -> m t
mapMOf LensLike (WrappedMonad m) s t a a
b forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a.
(Monad m, Plated a) =>
(a -> m a) -> a -> m a
transformM
{-# INLINE transformMOn #-}

-- | Transform every element in a tree using a user supplied 'Traversal' in a bottom-up manner with a monadic effect.
--
-- @
-- 'transformMOf' :: 'Monad' m => 'Traversal'' a a -> (a -> m a) -> a -> m a
-- @
transformMOf :: Monad m => LensLike (WrappedMonad m) a b a b -> (b -> m b) -> a -> m b
transformMOf :: forall (m :: * -> *) a b.
Monad m =>
LensLike (WrappedMonad m) a b a b -> (b -> m b) -> a -> m b
transformMOf LensLike (WrappedMonad m) a b a b
l b -> m b
f = a -> m b
go where
  go :: a -> m b
go a
t = forall (m :: * -> *) s t a b.
LensLike (WrappedMonad m) s t a b -> (a -> m b) -> s -> m t
mapMOf LensLike (WrappedMonad m) a b a b
l a -> m b
go a
t forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= b -> m b
f
{-# INLINE transformMOf #-}

-- | Transform every element in a tree that lies in a region indicated by a supplied 'Traversal', walking with a user supplied 'Traversal' in
-- a bottom-up manner with a monadic effect.
--
-- @
-- 'transformMOnOf' :: 'Monad' m => 'Traversal'' s a -> 'Traversal'' a a -> (a -> m a) -> s -> m s
-- @
transformMOnOf :: Monad m => LensLike (WrappedMonad m) s t a b -> LensLike (WrappedMonad m) a b a b -> (b -> m b) -> s -> m t
transformMOnOf :: forall (m :: * -> *) s t a b.
Monad m =>
LensLike (WrappedMonad m) s t a b
-> LensLike (WrappedMonad m) a b a b -> (b -> m b) -> s -> m t
transformMOnOf LensLike (WrappedMonad m) s t a b
b LensLike (WrappedMonad m) a b a b
l = forall (m :: * -> *) s t a b.
LensLike (WrappedMonad m) s t a b -> (a -> m b) -> s -> m t
mapMOf LensLike (WrappedMonad m) s t a b
b forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a b.
Monad m =>
LensLike (WrappedMonad m) a b a b -> (b -> m b) -> a -> m b
transformMOf LensLike (WrappedMonad m) a b a b
l
{-# INLINE transformMOnOf #-}

-------------------------------------------------------------------------------
-- Holes and Contexts
-------------------------------------------------------------------------------

-- | Return a list of all of the editable contexts for every location in the structure, recursively.
--
-- @
-- propUniverse x = 'universe' x '==' 'map' 'Control.Comonad.Store.Class.pos' ('contexts' x)
-- propId x = 'all' ('==' x) ['Control.Lens.Internal.Context.extract' w | w <- 'contexts' x]
-- @
--
-- @
-- 'contexts' ≡ 'contextsOf' 'plate'
-- @
contexts :: Plated a => a -> [Context a a a]
contexts :: forall a. Plated a => a -> [Context a a a]
contexts = forall a. ATraversal' a a -> a -> [Context a a a]
contextsOf forall a. Plated a => Traversal' a a
plate
{-# INLINE contexts #-}

-- | Return a list of all of the editable contexts for every location in the structure, recursively, using a user-specified 'Traversal' to walk each layer.
--
-- @
-- propUniverse l x = 'universeOf' l x '==' 'map' 'Control.Comonad.Store.Class.pos' ('contextsOf' l x)
-- propId l x = 'all' ('==' x) ['Control.Lens.Internal.Context.extract' w | w <- 'contextsOf' l x]
-- @
--
-- @
-- 'contextsOf' :: 'Traversal'' a a -> a -> ['Context' a a a]
-- @
contextsOf :: ATraversal' a a -> a -> [Context a a a]
contextsOf :: forall a. ATraversal' a a -> a -> [Context a a a]
contextsOf ATraversal' a a
l a
x = forall (p :: * -> * -> *) (w :: * -> * -> * -> *) a b.
Sellable p w =>
p a (w a b b)
sell a
x forall a. a -> [a] -> [a]
: forall {t}. [Context a a t] -> [Context a a t]
f (forall a b. (a -> b) -> [a] -> [b]
map forall (w :: * -> * -> * -> *) a b t.
IndexedComonadStore w =>
w a b t -> Context a b t
context (forall (p :: * -> * -> *) a s t.
Conjoined p =>
Over p (Bazaar p a a) s t a a -> s -> [Pretext p a a t]
holesOf ATraversal' a a
l a
x)) where
  f :: [Context a a t] -> [Context a a t]
f [Context a a t]
xs = do
    Context a -> t
ctx a
child <- [Context a a t]
xs
    Context a -> a
cont a
y <- forall a. ATraversal' a a -> a -> [Context a a a]
contextsOf ATraversal' a a
l a
child
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b t. (b -> t) -> a -> Context a b t
Context (a -> t
ctx forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
cont) a
y
{-# INLINE contextsOf #-}

-- | Return a list of all of the editable contexts for every location in the structure in an areas indicated by a user supplied 'Traversal', recursively using 'plate'.
--
-- @
-- 'contextsOn' b ≡ 'contextsOnOf' b 'plate'
-- @
--
-- @
-- 'contextsOn' :: 'Plated' a => 'Traversal'' s a -> s -> ['Context' a a s]
-- @
contextsOn :: Plated a => ATraversal s t a a -> s -> [Context a a t]
contextsOn :: forall a s t.
Plated a =>
ATraversal s t a a -> s -> [Context a a t]
contextsOn ATraversal s t a a
b = forall s t a.
ATraversal s t a a -> ATraversal' a a -> s -> [Context a a t]
contextsOnOf ATraversal s t a a
b forall a. Plated a => Traversal' a a
plate
{-# INLINE contextsOn #-}

-- | Return a list of all of the editable contexts for every location in the structure in an areas indicated by a user supplied 'Traversal', recursively using
-- another user-supplied 'Traversal' to walk each layer.
--
-- @
-- 'contextsOnOf' :: 'Traversal'' s a -> 'Traversal'' a a -> s -> ['Context' a a s]
-- @
contextsOnOf :: ATraversal s t a a -> ATraversal' a a -> s -> [Context a a t]
contextsOnOf :: forall s t a.
ATraversal s t a a -> ATraversal' a a -> s -> [Context a a t]
contextsOnOf ATraversal s t a a
b ATraversal' a a
l = forall {t}. [Context a a t] -> [Context a a t]
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall (w :: * -> * -> * -> *) a b t.
IndexedComonadStore w =>
w a b t -> Context a b t
context forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) a s t.
Conjoined p =>
Over p (Bazaar p a a) s t a a -> s -> [Pretext p a a t]
holesOf ATraversal s t a a
b where
  f :: [Context a a t] -> [Context a a t]
f [Context a a t]
xs = do
    Context a -> t
ctx a
child <- [Context a a t]
xs
    Context a -> a
cont a
y <- forall a. ATraversal' a a -> a -> [Context a a a]
contextsOf ATraversal' a a
l a
child
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b t. (b -> t) -> a -> Context a b t
Context (a -> t
ctx forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
cont) a
y
{-# INLINE contextsOnOf #-}

-- | The one-level version of 'context'. This extracts a list of the immediate children as editable contexts.
--
-- Given a context you can use 'Control.Comonad.Store.Class.pos' to see the values, 'Control.Comonad.Store.Class.peek' at what the structure would be like with an edited result, or simply 'Control.Lens.Internal.Context.extract' the original structure.
--
-- @
-- propChildren x = 'children' l x '==' 'map' 'Control.Comonad.Store.Class.pos' ('holes' l x)
-- propId x = 'all' ('==' x) ['Control.Lens.Internal.Context.extract' w | w <- 'holes' l x]
-- @
--
-- @
-- 'holes' = 'holesOf' 'plate'
-- @
holes :: Plated a => a -> [Pretext (->) a a a]
holes :: forall a. Plated a => a -> [Pretext (->) a a a]
holes = forall (p :: * -> * -> *) a s t.
Conjoined p =>
Over p (Bazaar p a a) s t a a -> s -> [Pretext p a a t]
holesOf forall a. Plated a => Traversal' a a
plate
{-# INLINE holes #-}

-- | An alias for 'holesOf', provided for consistency with the other combinators.
--
-- @
-- 'holesOn' ≡ 'holesOf'
-- @
--
-- @
-- 'holesOn' :: 'Iso'' s a                -> s -> ['Pretext' (->) a a s]
-- 'holesOn' :: 'Lens'' s a               -> s -> ['Pretext' (->) a a s]
-- 'holesOn' :: 'Traversal'' s a          -> s -> ['Pretext' (->) a a s]
-- 'holesOn' :: 'IndexedLens'' i s a      -> s -> ['Pretext' ('Control.Lens.Internal.Indexed.Indexed' i) a a s]
-- 'holesOn' :: 'IndexedTraversal'' i s a -> s -> ['Pretext' ('Control.Lens.Internal.Indexed.Indexed' i) a a s]
-- @
holesOn :: Conjoined p => Over p (Bazaar p a a) s t a a -> s -> [Pretext p a a t]
holesOn :: forall (p :: * -> * -> *) a s t.
Conjoined p =>
Over p (Bazaar p a a) s t a a -> s -> [Pretext p a a t]
holesOn = forall (p :: * -> * -> *) a s t.
Conjoined p =>
Over p (Bazaar p a a) s t a a -> s -> [Pretext p a a t]
holesOf
{-# INLINE holesOn #-}

-- | Extract one level of 'holes' from a container in a region specified by one 'Traversal', using another.
--
-- @
-- 'holesOnOf' b l ≡ 'holesOf' (b '.' l)
-- @
--
-- @
-- 'holesOnOf' :: 'Iso'' s a       -> 'Iso'' a a                -> s -> ['Pretext' (->) a a s]
-- 'holesOnOf' :: 'Lens'' s a      -> 'Lens'' a a               -> s -> ['Pretext' (->) a a s]
-- 'holesOnOf' :: 'Traversal'' s a -> 'Traversal'' a a          -> s -> ['Pretext' (->) a a s]
-- 'holesOnOf' :: 'Lens'' s a      -> 'IndexedLens'' i a a      -> s -> ['Pretext' ('Control.Lens.Internal.Indexed.Indexed' i) a a s]
-- 'holesOnOf' :: 'Traversal'' s a -> 'IndexedTraversal'' i a a -> s -> ['Pretext' ('Control.Lens.Internal.Indexed.Indexed' i) a a s]
-- @
holesOnOf :: Conjoined p
          => LensLike (Bazaar p  r r) s t a b
          -> Over p (Bazaar p r r) a b r r
          -> s -> [Pretext p r r t]
holesOnOf :: forall (p :: * -> * -> *) r s t a b.
Conjoined p =>
LensLike (Bazaar p r r) s t a b
-> Over p (Bazaar p r r) a b r r -> s -> [Pretext p r r t]
holesOnOf LensLike (Bazaar p r r) s t a b
b Over p (Bazaar p r r) a b r r
l = forall (p :: * -> * -> *) a s t.
Conjoined p =>
Over p (Bazaar p a a) s t a a -> s -> [Pretext p a a t]
holesOf (LensLike (Bazaar p r r) s t a b
b forall b c a. (b -> c) -> (a -> b) -> a -> c
. Over p (Bazaar p r r) a b r r
l)
{-# INLINE holesOnOf #-}

-------------------------------------------------------------------------------
-- Paramorphisms
-------------------------------------------------------------------------------

-- | Perform a fold-like computation on each value, technically a paramorphism.
--
-- @
-- 'paraOf' :: 'Fold' a a -> (a -> [r] -> r) -> a -> r
-- @
paraOf :: Getting (Endo [a]) a a -> (a -> [r] -> r) -> a -> r
paraOf :: forall a r. Getting (Endo [a]) a a -> (a -> [r] -> r) -> a -> r
paraOf Getting (Endo [a]) a a
l a -> [r] -> r
f = a -> r
go where
  go :: a -> r
go a
a = a -> [r] -> r
f a
a (a -> r
go forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a s. Getting (Endo [a]) s a -> s -> [a]
toListOf Getting (Endo [a]) a a
l a
a)
{-# INLINE paraOf #-}

-- | Perform a fold-like computation on each value, technically a paramorphism.
--
-- @
-- 'para' ≡ 'paraOf' 'plate'
-- @
para :: Plated a => (a -> [r] -> r) -> a -> r
para :: forall a r. Plated a => (a -> [r] -> r) -> a -> r
para = forall a r. Getting (Endo [a]) a a -> (a -> [r] -> r) -> a -> r
paraOf forall a. Plated a => Traversal' a a
plate
{-# INLINE para #-}

-------------------------------------------------------------------------------
-- Compos
-------------------------------------------------------------------------------

-- $compos
--
-- Provided for compatibility with Björn Bringert's @compos@ library.
--
-- Note: Other operations from compos that were inherited by @uniplate@ are /not/ included
-- to avoid having even more redundant names for the same operators. For comparison:
--
-- @
-- 'composOpMonoid' ≡ 'foldMapOf' 'plate'
-- 'composOpMPlus' f ≡ 'msumOf' ('plate' '.' 'Control.Lens.Getter.to' f)
-- 'composOp' ≡ 'descend' ≡ 'over' 'plate'
-- 'composOpM' ≡ 'descendM' ≡ 'mapMOf' 'plate'
-- 'composOpM_' ≡ 'descendM_' ≡ 'mapMOf_' 'plate'
-- @

-- | Fold the immediate children of a 'Plated' container.
--
-- @
-- 'composOpFold' z c f = 'foldrOf' 'plate' (c '.' f) z
-- @
composOpFold :: Plated a => b -> (b -> b -> b) -> (a -> b) -> a -> b
composOpFold :: forall a b. Plated a => b -> (b -> b -> b) -> (a -> b) -> a -> b
composOpFold b
z b -> b -> b
c a -> b
f = forall r s a. Getting (Endo r) s a -> (a -> r -> r) -> r -> s -> r
foldrOf forall a. Plated a => Traversal' a a
plate (b -> b -> b
c forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) b
z
{-# INLINE composOpFold #-}

-------------------------------------------------------------------------------
-- Parts
-------------------------------------------------------------------------------

-- | The original @uniplate@ combinator, implemented in terms of 'Plated' as a 'Lens'.
--
-- @
-- 'parts' ≡ 'partsOf' 'plate'
-- @
--
-- The resulting 'Lens' is safer to use as it ignores 'over-application' and deals gracefully with under-application,
-- but it is only a proper 'Lens' if you don't change the list 'length'!
parts :: Plated a => Lens' a [a]
parts :: forall a. Plated a => Lens' a [a]
parts = forall (f :: * -> *) s t a.
Functor f =>
Traversing (->) f s t a a -> LensLike f s t [a] [a]
partsOf forall a. Plated a => Traversal' a a
plate
{-# INLINE parts #-}

-------------------------------------------------------------------------------
-- Generics
-------------------------------------------------------------------------------

-- | Implement 'plate' operation for a type using its 'Generic' instance.
--
-- Note: the behavior may be different than with 'uniplate' in some special cases.
-- 'gplate' doesn't look through other types in a group of mutually
-- recursive types.
--
-- For example consider mutually recursive even and odd natural numbers:
--
-- >>> data Even = Z | E Odd deriving (Show, Generic, Data); data Odd = O Even deriving (Show, Generic, Data)
--
-- Then 'uniplate', which is based on `Data`, finds
-- all even numbers less or equal than four:
--
-- >>> import Data.Data.Lens (uniplate)
-- >>> universeOf uniplate (E (O (E (O Z))))
-- [E (O (E (O Z))),E (O Z),Z]
--
-- but 'gplate' doesn't see through @Odd@.
--
-- >>> universeOf gplate (E (O (E (O Z))))
-- [E (O (E (O Z)))]
--
-- If using 'Data' is not an option, you can still write the traversal manually.
-- It is sometimes useful to use helper traversals
--
-- >>> :{
-- let oddeven :: Traversal' Odd Even
--     oddeven f (O n) = O <$> f n
--     evenplate :: Traversal' Even Even
--     evenplate f Z     = pure Z
--     evenplate f (E n) = E <$> oddeven f n
-- :}
--
-- >>> universeOf evenplate (E (O (E (O Z))))
-- [E (O (E (O Z))),E (O Z),Z]
--
gplate :: (Generic a, GPlated a (Rep a)) => Traversal' a a
gplate :: forall a. (Generic a, GPlated a (Rep a)) => Traversal' a a
gplate a -> f a
f a
x = forall a x. Generic a => Rep a x -> a
GHC.Generics.to forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} a (g :: k -> *) (p :: k).
GPlated a g =>
Traversal' (g p) a
gplate' a -> f a
f (forall a x. Generic a => a -> Rep a x
GHC.Generics.from a
x)
{-# INLINE gplate #-}

class GPlated a g where
  gplate' :: Traversal' (g p) a

instance GPlated a f => GPlated a (M1 i c f) where
  gplate' :: forall (p :: k). Traversal' (M1 i c f p) a
gplate' a -> f a
f (M1 f p
x) = forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} a (g :: k -> *) (p :: k).
GPlated a g =>
Traversal' (g p) a
gplate' a -> f a
f f p
x
  {-# INLINE gplate' #-}

instance (GPlated a f, GPlated a g) => GPlated a (f :+: g) where
  gplate' :: forall (p :: k). Traversal' ((:+:) f g p) a
gplate' a -> f a
f (L1 f p
x) = forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
L1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} a (g :: k -> *) (p :: k).
GPlated a g =>
Traversal' (g p) a
gplate' a -> f a
f f p
x
  gplate' a -> f a
f (R1 g p
x) = forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
R1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} a (g :: k -> *) (p :: k).
GPlated a g =>
Traversal' (g p) a
gplate' a -> f a
f g p
x
  {-# INLINE gplate' #-}

instance (GPlated a f, GPlated a g) => GPlated a (f :*: g) where
  gplate' :: forall (p :: k). Traversal' ((:*:) f g p) a
gplate' a -> f a
f (f p
x :*: g p
y) = forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
(:*:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} a (g :: k -> *) (p :: k).
GPlated a g =>
Traversal' (g p) a
gplate' a -> f a
f f p
x forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall {k} a (g :: k -> *) (p :: k).
GPlated a g =>
Traversal' (g p) a
gplate' a -> f a
f g p
y
  {-# INLINE gplate' #-}

instance {-# OVERLAPPING #-} GPlated a (K1 i a) where
  gplate' :: forall (p :: k). Traversal' (K1 i a p) a
gplate' a -> f a
f (K1 a
x) = forall k i c (p :: k). c -> K1 i c p
K1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f a
f a
x
  {-# INLINE gplate' #-}

instance GPlated a (K1 i b) where
  gplate' :: forall (p :: k). Traversal' (K1 i b p) a
gplate' a -> f a
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE gplate' #-}

instance GPlated a U1 where
  gplate' :: forall (p :: k). Traversal' (U1 p) a
gplate' a -> f a
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE gplate' #-}

instance GPlated a V1 where
  gplate' :: forall (p :: k). Traversal' (V1 p) a
gplate' a -> f a
_ V1 p
v = V1 p
v seq :: forall a b. a -> b -> b
`seq` forall a. HasCallStack => [Char] -> a
error [Char]
"GPlated/V1"
  {-# INLINE gplate' #-}

instance GPlated a (URec b) where
  gplate' :: forall (p :: k). Traversal' (URec b p) a
gplate' a -> f a
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE gplate' #-}

-- | Implement 'plate' operation for a type using its 'Generic1' instance.
gplate1 :: (Generic1 f, GPlated1 f (Rep1 f)) => Traversal' (f a) (f a)
gplate1 :: forall {k} (f :: k -> *) (a :: k).
(Generic1 f, GPlated1 f (Rep1 f)) =>
Traversal' (f a) (f a)
gplate1 f a -> f (f a)
f f a
x = forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
GHC.Generics.to1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
GPlated1 f g =>
Traversal' (g a) (f a)
gplate1' f a -> f (f a)
f (forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
GHC.Generics.from1 f a
x)
{-# INLINE gplate1 #-}

class GPlated1 f g where
  gplate1' :: Traversal' (g a) (f a)

-- | recursive match
instance GPlated1 f g => GPlated1 f (M1 i c g) where
  gplate1' :: forall (a :: k). Traversal' (M1 i c g a) (f a)
gplate1' f a -> f (f a)
f (M1 g a
x) = forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
GPlated1 f g =>
Traversal' (g a) (f a)
gplate1' f a -> f (f a)
f g a
x
  {-# INLINE gplate1' #-}

-- | recursive match
instance (GPlated1 f g, GPlated1 f h) => GPlated1 f (g :+: h) where
  gplate1' :: forall (a :: k). Traversal' ((:+:) g h a) (f a)
gplate1' f a -> f (f a)
f (L1 g a
x) = forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
L1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
GPlated1 f g =>
Traversal' (g a) (f a)
gplate1' f a -> f (f a)
f g a
x
  gplate1' f a -> f (f a)
f (R1 h a
x) = forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
R1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
GPlated1 f g =>
Traversal' (g a) (f a)
gplate1' f a -> f (f a)
f h a
x
  {-# INLINE gplate1' #-}

-- | recursive match
instance (GPlated1 f g, GPlated1 f h) => GPlated1 f (g :*: h) where
  gplate1' :: forall (a :: k). Traversal' ((:*:) g h a) (f a)
gplate1' f a -> f (f a)
f (g a
x :*: h a
y) = forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
(:*:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
GPlated1 f g =>
Traversal' (g a) (f a)
gplate1' f a -> f (f a)
f g a
x forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
GPlated1 f g =>
Traversal' (g a) (f a)
gplate1' f a -> f (f a)
f h a
y
  {-# INLINE gplate1' #-}

-- | ignored
instance GPlated1 f (K1 i a) where
  gplate1' :: forall (a :: k). Traversal' (K1 i a a) (f a)
gplate1' f a -> f (f a)
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE gplate1' #-}

-- | ignored
instance GPlated1 f Par1 where
  gplate1' :: forall a. Traversal' (Par1 a) (f a)
gplate1' f a -> f (f a)
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE gplate1' #-}

-- | ignored
instance GPlated1 f U1 where
  gplate1' :: forall (a :: k). Traversal' (U1 a) (f a)
gplate1' f a -> f (f a)
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE gplate1' #-}

-- | ignored
instance GPlated1 f V1 where
  gplate1' :: forall (a :: k). Traversal' (V1 a) (f a)
gplate1' f a -> f (f a)
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE gplate1' #-}

-- | match
instance {-# OVERLAPPING #-} GPlated1 f (Rec1 f) where
  gplate1' :: forall (a :: k). Traversal' (Rec1 f a) (f a)
gplate1' f a -> f (f a)
f (Rec1 f a
x) = forall k (f :: k -> *) (p :: k). f p -> Rec1 f p
Rec1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f a -> f (f a)
f f a
x
  {-# INLINE gplate1' #-}

-- | ignored
instance GPlated1 f (Rec1 g) where
  gplate1' :: forall (a :: k). Traversal' (Rec1 g a) (f a)
gplate1' f a -> f (f a)
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE gplate1' #-}

-- | recursive match under outer 'Traversable' instance
instance (Traversable t, GPlated1 f g) => GPlated1 f (t :.: g) where
  gplate1' :: forall (a :: k1). Traversal' ((:.:) t g a) (f a)
gplate1' f a -> f (f a)
f (Comp1 t (g a)
x) = forall k2 k1 (f :: k2 -> *) (g :: k1 -> k2) (p :: k1).
f (g p) -> (:.:) f g p
Comp1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
GPlated1 f g =>
Traversal' (g a) (f a)
gplate1' f a -> f (f a)
f) t (g a)
x
  {-# INLINE gplate1' #-}

-- | ignored
instance GPlated1 f (URec a) where
  gplate1' :: forall (a :: k). Traversal' (URec a a) (f a)
gplate1' f a -> f (f a)
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE gplate1' #-}