module Generics.MultiRec.Transformations.Path (
module Generics.MultiRec.Transformations.Path
, Ctxs(..), Ctx(..)
) where
import Prelude as P hiding ( mapM, sequence )
import Generics.MultiRec hiding ( show, foldM )
import Generics.MultiRec.Zipper ( Ctxs(..), Ctx(..) )
import Control.Monad.State hiding ( foldM, mapM, sequence )
import Data.Traversable ( Traversable, mapM, sequence )
import Generics.MultiRec.CountIs
type Path phi t i = Ctxs phi t (K0 ()) i
type Dir f t i = Ctx f t (K0 ()) i
data WithRef phi top r a = InR { unInR :: PF phi r a }
| Ref { unRef :: Path phi a top }
type HWithRef phi top t = HFix (WithRef phi top) t
data Insert phi top ix where
Insert :: phi t -> Path phi t ix -> HWithRef phi top t -> Insert phi top ix
(<.>) :: forall phi a b c. Path phi b a -> Path phi c b -> Path phi c a
Empty <.> p2 = p2
(Push p x xs) <.> p2 = Push p x (xs <.> p2)
newtype ConIndex = CI Int deriving (Eq, Num)
instance Show ConIndex where
show (CI (1)) = ""
show (CI n ) = "_" ++ show n ++ " "
class ShowPath f where
showsPrecPath :: ShowS -> ConIndex -> Int -> Dir f i t -> ShowS
instance (ShowPath f, ShowPath g) => ShowPath (f :+: g) where
showsPrecPath r d n (CL p) = showsPrecPath r d n p
showsPrecPath r d n (CR p) = showsPrecPath r d n p
instance (ShowPath f, ShowPath g, CountIs f) => ShowPath (f :*: g) where
showsPrecPath r d n (C1 p _) = showsPrecPath r d n p
showsPrecPath r d n (C2 _ p) =
let newd = if d == 1 then 1 else d + CI (countIs (undefined :: f r ix))
in showsPrecPath r newd n p
instance (ShowPath f) => ShowPath (f :>: ix) where
showsPrecPath r d n (CTag p) = showsPrecPath r d n p
instance (ShowPath f, Constructor c) => ShowPath (C c f) where
showsPrecPath r d n (CC p) = let name = conName (undefined :: C c f r ix)
in showParen (n > 10) $ showString name
. showsPrecPath r 0 11 p
instance ShowPath (K a) where showsPrecPath _ _ _ _ = id
instance ShowPath U where showsPrecPath _ _ _ _ = id
instance ShowPath (I ix) where
showsPrecPath r d n CId = shows d . r
instance (ShowPath f) => ShowPath (Maybe :.: f) where
showsPrecPath r d n (CCM p) = shows d
. showParen (n > 10)
( showString "Maybe_0 "
. showsPrecPath r (1) 11 p)
instance (ShowPath f) => ShowPath ([] :.: f) where
showsPrecPath r d n (CCL l1 p l2) = shows d
. showParen (n > 10)
( showString "List_"
. P.showsPrec 11 (length l1)
. showChar ' '
. showsPrecPath r (1) 11 p)
showsPrecPathC :: (ShowPath (PF phi))
=> ConIndex -> Int -> Path phi t i -> ShowS
showsPrecPathC d n Empty = showString "End"
showsPrecPathC d n (Push w p ps) = showsPrecPath (showsPrecPathC d n ps) d n p
instance (ShowPath (PF phi)) => Show (Path phi t i) where
showsPrec = showsPrecPathC 0
instance (HFunctor phi (PF phi), HShow phi (PF phi), El phi ix, ShowPath (PF phi))
=> Show (HWithRef phi top ix) where
showsPrec = showWR proof
instance (HFunctor phi (PF phi), HShow phi (PF phi), El phi ix, ShowPath (PF phi))
=> Show (Insert phi top ix) where
showsPrec n (Insert w p r) = showParen (n > 10) $
showString "Insert " . spaces [P.showsPrec 11 p, showWR w 11 r]
showWR :: forall phi top ix.
(HFunctor phi (PF phi), HShow phi (PF phi), ShowPath (PF phi))
=> phi ix -> Int -> HWithRef phi top ix -> ShowS
showWR w n (HIn (InR p)) = showParen (n > 10) $ spaces (("InR"++) : map ($ 11) x) where
f :: forall ix. phi ix -> HWithRef phi top ix -> K0 [Int -> ShowS] ix
f w wr = K0 [\n -> showWR w n wr]
r :: PF phi (K0 [Int -> ShowS]) ix
r = hmap f w p
x :: [Int -> ShowS]
x = hShowsPrecAlg w r
showWR w n (HIn (Ref p)) = showParen (n > 10) $ showString "Ref " . P.showsPrec 11 p
mapP :: forall m phi i t. (Monad m, Fam phi, MapP phi (PF phi))
=> phi i -> Path phi t i -> (phi t -> t -> m t) -> i -> m i
mapP w1 Empty f = f w1
mapP w1 (Push w2 y p) f =
liftM (to w1) . mapP' (\w -> liftM I0 . mapP w p f . unI0) w1 y . from w1
class MapP phi f where
mapP' :: Monad m
=> (phi t -> r t -> m (r t))
-> phi ix -> Dir f t ix -> f r ix -> m (f r ix)
instance MapP phi U where mapP' f phi p = return
instance MapP phi (K a) where mapP' f phi p = return
instance (El phi ix) => MapP phi (I ix) where
mapP' f phi CId (I x) = liftM I (f proof x)
instance (MapP phi f, MapP phi g) => MapP phi (f :+: g) where
mapP' f phi (CL p) (L x) = liftM L (mapP' f phi p x)
mapP' f phi (CR p) (R x) = liftM R (mapP' f phi p x)
mapP' _ _ _ _ = fail "mapP': inconsistent sum"
instance (MapP phi f, MapP phi g) => MapP phi (f :*: g) where
mapP' f phi (C1 p _) (x :*: y) = liftM2 (:*:) (mapP' f phi p x) (return y)
mapP' f phi (C2 _ p) (x :*: y) = liftM2 (:*:) (return x) (mapP' f phi p y)
instance (MapP phi f) => MapP phi (C c f) where
mapP' f phi (CC p) (C x) = liftM C (mapP' f phi p x)
instance (MapP phi f) => MapP phi (f :>: ix) where
mapP' f phi (CTag p) (Tag x) = liftM Tag (mapP' f phi p x)
instance (MapP phi f) => MapP phi (Maybe :.: f) where
mapP' f phi (CCM p) = liftM D . sequence . liftM (mapP' f phi p) . unD
instance (MapP phi f) => MapP phi ([] :.: f) where
mapP' f phi (CCL x p _) = liftM D . mapMwithI (\i ->
if i == length x
then mapP' f phi p
else return) . unD
mapPR :: forall phi top t a. (Fam phi, MapP phi (PF phi))
=> phi a -> Path phi t a
-> (phi t -> HWithRef phi top t -> Maybe (HWithRef phi top t))
-> HWithRef phi top a -> Maybe (HWithRef phi top a)
mapPR _ _ _ (HIn (Ref _)) = Nothing
mapPR w1 Empty f a = f w1 a
mapPR w1 (Push w2 y p) f (HIn (InR a)) =
liftM (HIn . InR) . mapP' (\w -> mapPR w p f) w1 y $ a
mapMwithI :: (Monad m, Traversable t) => (Int -> a -> m b) -> t a -> m (t b)
mapMwithI f ta = evalStateT (mapM g ta) 0 where
g a = do i <- get
put $ i+1
lift $ f i a