7 | import Control.Monad.Identity
8 | import Control.Applicative.Const
14 | Projector : ((Type -> Type) -> Type) -> Type -> Type
15 | Projector p a = forall f. p f -> a -> f a
29 | interface Multiplate (0 p : (Type -> Type) -> Type) where
34 | multiplate : Applicative f => p f -> p f
37 | mkPlate : Applicative f => (forall a. Projector p a -> a -> f a) -> p f
40 | public export %inline
41 | purePlate : Multiplate p => Applicative f => p f
42 | purePlate = mkPlate (\_ => pure)
45 | public export %inline
46 | applyNaturalTransform : Multiplate p => Applicative g => (forall a. f a -> g a) -> p f -> p g
47 | applyNaturalTransform f p = mkPlate $
\proj, x => f $
proj p x
49 | public export %inline
50 | fromIdentity : Multiplate p => Applicative f => p Identity -> p f
51 | fromIdentity = applyNaturalTransform (pure . runIdentity)
56 | public export %inline
57 | andThenM : Monad m => Multiplate p => Lazy (p m) -> Lazy (p m) -> p m
58 | andThenM p1 p2 = mkPlate $
\proj, x => do
62 | infixl 5 `andThenId`
65 | public export %inline
66 | andThenId : Multiplate p => Applicative m => Lazy (p m) -> Lazy (p Identity) -> p m
67 | andThenId p1 p2 = mkPlate $
\proj, x => proj p1 x <&> \x' => runIdentity (proj p2 x')
72 | public export %inline
73 | idAndThen : Multiplate p => Applicative m => Lazy (p Identity) -> Lazy (p m) -> p m
74 | idAndThen p1 p2 = mkPlate $
\proj, x =>
75 | let x' = runIdentity $
proj p1 x
81 | public export %inline
82 | orElse : Alternative m => Multiplate p => Lazy (p m) -> Lazy (p m) -> p m
83 | orElse p1 p2 = mkPlate $
\proj, x => proj p1 x <|> proj p2 x
87 | public export covering
88 | postorderMap : Multiplate p => Monad m => p m -> p m
89 | postorderMap p = multiplate (postorderMap p) `andThenM` p
93 | public export covering
94 | preorderMap : Multiplate p => Monad m => p m -> p m
95 | preorderMap p = p `andThenM` multiplate (preorderMap p)
98 | public export %inline
99 | append : Multiplate p => Monoid o => Lazy (p (Const o)) -> Lazy (p (Const o)) -> p (Const o)
100 | append p1 p2 = mkPlate $
\proj, x => proj p1 x <+> proj p2 x
112 | public export covering
113 | preorderFold : Multiplate p => Monoid o => p (Const o) -> p (Const o)
114 | preorderFold p = p `append` multiplate (preorderFold p)
125 | public export covering
126 | postorderFold : Multiplate p => Monoid o => p (Const o) -> p (Const o)
127 | postorderFold p = multiplate (postorderFold p) `append` p
130 | public export %inline
131 | catchWith : Multiplate p => Applicative f => p Maybe -> p f -> p f
132 | catchWith p def = mkPlate $
\proj, x => case proj p x of
134 | Nothing => proj def x
139 | public export %inline
140 | catch : Multiplate p => Applicative f => p Maybe -> p f
141 | catch p = mkPlate $
\proj, x => case proj p x of
151 | interface Multiplate p => HasProjection p a where
154 | project : Projector p a
159 | public export %inline
160 | traverseFor : HasProjection p a => p Identity -> a -> a
161 | traverseFor p x = runIdentity $
project p x
164 | public export %inline
165 | foldFor : HasProjection p a => p (Const o) -> a -> o
166 | foldFor p x = runConst $
project p x
178 | interface HasProjection p a => HasField p a where
182 | inject : Applicative f => (a -> f a) -> p f
183 | inject f = update f purePlate
187 | update : (a -> f a) -> p f -> p f
190 | public export %inline
191 | injectPure : HasField p a => Applicative f => (a -> a) -> p f
192 | injectPure f = inject $
pure . f