{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Generics.MRSOP.Zipper where
import Generics.MRSOP.Base hiding (Cons , Nil)
data Loc :: (kon -> *) -> [*] -> [[[Atom kon]]] -> Nat -> * where
Loc :: IsNat ix => El fam ix -> Ctxs ki fam cs iy ix -> Loc ki fam cs iy
data Ctxs :: (kon -> *) -> [*] -> [[[Atom kon]]] -> Nat -> Nat -> * where
Nil :: Ctxs ki fam cs ix ix
Cons :: (IsNat ix , IsNat a , IsNat b)
=> Ctx ki fam (Lkup ix cs) b -> Ctxs ki fam cs a ix
-> Ctxs ki fam cs a b
data Ctx :: (kon -> *) -> [*] -> [[Atom kon]] -> Nat -> * where
Ctx :: Constr c n
-> NPHole ki fam ix (Lkup n c)
-> Ctx ki fam c ix
data NPHole :: (kon -> *) -> [*] -> Nat -> [Atom kon] -> * where
H :: PoA ki (El fam) xs -> NPHole ki fam ix ('I ix : xs)
T :: NA ki (El fam) x -> NPHole ki fam ix xs -> NPHole ki fam ix (x : xs)
data NPHoleE :: (kon -> *) -> [*] -> [Atom kon] -> * where
ExistsIX :: IsNat ix => El fam ix -> NPHole ki fam ix xs -> NPHoleE ki fam xs
mkNPHole :: PoA ki (El fam) xs -> Maybe (NPHoleE ki fam xs)
mkNPHole NP0 = Nothing
mkNPHole (NA_I x :* xs) = Just (ExistsIX x (H xs))
mkNPHole (NA_K k :* xs)
= do (ExistsIX el c) <- mkNPHole xs
return (ExistsIX el (T (NA_K k) c))
fillNPHole :: (IsNat ix) => El fam ix -> NPHole ki fam ix xs -> PoA ki (El fam) xs
fillNPHole x (H xs) = NA_I x :* xs
fillNPHole x (T y xs) = y :* fillNPHole x xs
walkNPHole :: (IsNat ix) => El fam ix -> NPHole ki fam ix xs -> Maybe (NPHoleE ki fam xs)
walkNPHole el (H xs)
= do (ExistsIX el' c) <- mkNPHole xs
return (ExistsIX el' (T (NA_I el) c))
walkNPHole el (T na xs)
= do (ExistsIX el' c) <- walkNPHole el xs
return (ExistsIX el' (T na c))
first :: (forall ix . IsNat ix => El fam ix -> Ctx ki fam c ix -> a)
-> Rep ki (El fam) c -> Maybe a
first f el | Tag c p <- sop el
= do (ExistsIX el0 nphole) <- mkNPHole p
return (f el0 (Ctx c nphole))
fill :: (IsNat ix) => El fam ix -> Ctx ki fam c ix -> Rep ki (El fam) c
fill el (Ctx c nphole) = inj c (fillNPHole el nphole)
fillCtxs :: forall ix fam iy ki c. (IsNat ix, Family ki fam c) => El fam iy -> Ctxs ki fam c ix iy -> El fam ix
fillCtxs h Nil = h
fillCtxs h (Cons ctx ctxs) =
fillCtxs (sto @fam @ki @c $ fill h ctx) ctxs
next :: (IsNat ix)
=> (forall iy . IsNat iy => El fam iy -> Ctx ki fam c iy -> a)
-> El fam ix -> Ctx ki fam c ix -> Maybe a
next f el (Ctx c nphole)
= do (ExistsIX el' nphole') <- walkNPHole el nphole
return (f el' (Ctx c nphole'))
down :: (Family ki fam codes , IsNat ix)
=> Loc ki fam codes ix -> Maybe (Loc ki fam codes ix)
down (Loc el ctx)
= first (\el' ctx' -> Loc el' (Cons ctx' ctx))
(sfrom el)
up :: (Family ki fam codes, IsNat ix)
=> Loc ki fam codes ix -> Maybe (Loc ki fam codes ix)
up (Loc _ Nil) = Nothing
up (Loc el (Cons ctx ctxs)) = Just (Loc (sto $ fill el ctx) ctxs)
right :: (Family ki fam codes, IsNat ix)
=> Loc ki fam codes ix -> Maybe (Loc ki fam codes ix)
right (Loc _ Nil) = Nothing
right (Loc el (Cons ctx ctxs)) = next (\el' ctx' -> Loc el' (Cons ctx' ctxs)) el ctx
enter :: (Family ki fam codes , IsNat ix)
=> El fam ix -> Loc ki fam codes ix
enter el = Loc el Nil
leave :: (Family ki fam codes , IsNat ix)
=> Loc ki fam codes ix -> El fam ix
leave (Loc x Nil) = x
leave loc = maybe undefined leave $ up loc
update :: (Family ki fam codes , IsNat ix)
=> (forall iy . SNat iy -> El fam iy -> El fam iy)
-> Loc ki fam codes ix -> Loc ki fam codes ix
update f (Loc el ctxs) = Loc (f (getElSNat el) el) ctxs