module Generics.Pointless.Lenses.RecursionPatterns where
import Prelude hiding (Functor(..),fmap)
import Generics.Pointless.Combinators
import Generics.Pointless.Functors
import Generics.Pointless.Fctrable
import Generics.Pointless.Bifunctors
import Generics.Pointless.Bifctrable
import Generics.Pointless.RecursionPatterns
import Generics.Pointless.Lenses
import Generics.Pointless.Lenses.Combinators
inn_lns :: Mu a => Lens (F a a) a
inn_lns = Lens inn (out . fst) out
out_lns :: Mu a => Lens a (F a a)
out_lns = Lens out (inn . fst) inn
fmap_lns :: Fctrable f => Fix f -> Lens c a -> Lens (Rep f c) (Rep f a)
fmap_lns (f::Fix f) l = Lens get' put' create'
where get' = fmap f (get l)
put' = fmap f (put l) . fzip (fctr :: Fctr f) (create l)
create' = fmap f (create l)
fzip :: Fctr f -> (a -> c) -> (Rep f a,Rep f c) -> Rep f (a,c)
fzip I create = id
fzip K create = fst
fzip (f :*!: g) create = (fzip f create >< fzip g create) . distp
fzip (f :+!: g) create = (l -|- r) . dists
where l = fzip f create \/ fmap (fixF f) (id /\ create) . fst
r = fmap (fixF g) (id /\ create) . fst \/ fzip g create
hylo_lns :: (Mu b,Fctrable (PF b)) => b -> Lens (F b c) c -> Lens a (F b a) -> Lens a c
hylo_lns b g h = cata_lns b g .< ana_lns b h
ana_lns :: (Mu b,Fctrable (PF b)) => b -> Lens a (F b a) -> Lens a b
ana_lns (b::b) l = Lens get' put' create'
where get' = ana b (get l)
put' = accum b (put l) (fzip g create' . (id >< get l))
create' = cata b (create l)
g = fctr :: Fctr (PF b)
cata_lns :: (Mu a,Fctrable (PF a)) => a -> (Lens (F a b) b) -> Lens a b
cata_lns (a::a) l = Lens get' put' create'
where get' = cata a (get l)
put' = ana a (fzip f create' . (put l . (id >< fmap (fixF f) get') /\ snd) . (id >< out))
create' = ana a (create l)
f = fctr :: Fctr (PF a)
nat_lns :: (Mu a,Mu b,Fctrable (PF b)) => a -> NatLens (PF a) (PF b) -> Lens a b
nat_lns a l = ana_lns _L (l a .< out_lns)
binn_lns :: Bimu d => Lens (B d a (d a)) (d a)
binn_lns = Lens binn (bout . fst) bout
bout_lns :: Bimu d => Lens (d a) (B d a (d a))
bout_lns = Lens bout (binn . fst) binn
bmap_lns :: Bifctrable f => BFix f -> Lens c a -> NatLens (BRep f c) (BRep f a)
bmap_lns (f::BFix f) l (x::x) = Lens get' put' create'
where get' = bmap f (get l) idx
put' = bmap f (put l) idx . bzip x (bctr :: Bifctr f) (create l)
create' = bmap f (create l) idx
idx = id :: x -> x
bzip :: x -> Bifctr f -> (a -> c) -> (Rep (BRep f a) x,Rep (BRep f c) x) -> Rep (BRep f (a,c)) x
bzip x BI create = fst
bzip x BP create = id
bzip x BK create = fst
bzip x (f :*!| g) create = (bzip x f create >< bzip x g create) . distp
bzip (x::x) (f :+!| g) create = (l -|- r) . dists
where l = bzip x f create \/ bmap (fixB f) (id /\ create) idx . fst
r = bmap (fixB g) (id /\ create) idx . fst \/ bzip x g create
idx = id :: x -> x
gmap_lns :: (Mu (d c),Mu (d a),Fctrable (PF (d c)),Bifctrable (BF d),
F (d a) (d a) ~ B d a (d a),
F (d c) (d a) ~ B d c (d a))
=> d a -> Lens c a -> Lens (d c) (d a)
gmap_lns (da::d a) l = cata_lns _L (inn_lns .< (bmap_lns (fixB f) l) da)
where f = bctr :: Bifctr (BF d)