Skip to content

Instantly share code, notes, and snippets.

@AndrasKovacs
Last active August 29, 2015 14:05
Show Gist options
  • Save AndrasKovacs/2732f0432ec50500d880 to your computer and use it in GitHub Desktop.
Save AndrasKovacs/2732f0432ec50500d880 to your computer and use it in GitHub Desktop.
Two flavors of uniplate for indexed types.
-- Lens style ----------------------
-- Kudos for circed for holes and contexts in lens-style: http://stackoverflow.com/questions/25393870/how-can-holes-and-contexts-be-implemented-for-higher-kinded-types-in-a-lens-styl
{-# LANGUAGE GADTs, RankNTypes, PolyKinds, StandaloneDeriving, ScopedTypeVariables #-}
import Control.Applicative
import Control.Monad.Identity
class Uniplate1 (a :: k -> *) where
uniplate1 :: Applicative f => (forall i. a i -> f (a i)) -> a i -> f (a i)
data Some a where
Some :: a i -> Some a
descend :: Uniplate1 a => (forall i. a i -> a i) -> a i -> a i
descend f = runIdentity . uniplate1 (Identity . f)
descendM :: (Monad m, Uniplate1 a) => (forall i. a i -> m (a i)) -> a i -> m (a i)
descendM f = unwrapMonad . uniplate1 (WrapMonad . f)
transform :: Uniplate1 a => (forall i. a i -> a i) -> a i -> a i
transform f = f . descend (transform f)
transformM :: (Monad m, Uniplate1 a) => (forall i. a i -> m (a i)) -> a i -> m (a i)
transformM f = f <=< descendM (transformM f)
rewrite :: Uniplate1 a => (forall i. a i -> Maybe (a i)) -> a i -> a i
rewrite f = transform (\x -> maybe x (rewrite f) (f x))
rewriteM :: (Monad m, Uniplate1 a) => (forall i. a i -> m (Maybe (a i))) -> a i -> m (a i)
rewriteM f = transformM (\x -> maybe (return x) (rewriteM f) =<< f x)
children :: Uniplate1 a => a i -> [Some a]
children = getConst . uniplate1 (Const . (:[]) . Some)
universe :: Uniplate1 a => a i -> [Some a]
universe x = Some x : do {Some x <- children x; universe x}
-- uniplate style -----------------------
{-
{-# LANGUAGE RankNTypes, PolyKinds, GADTs, DeriveFunctor, TypeOperators, DataKinds #-}
import Control.Monad
type Nat a b = forall i. a i -> b i
type NatF f a b = forall i. a i -> f (b i)
data Children (a :: k -> *) (is :: [k]) where
Nil :: Children a '[]
(:>) :: a i -> Children a is -> Children a (i ': is)
infixr 5 :>
chToSome :: Children a is -> [Some a]
chToSome Nil = []
chToSome (x :> xs) = Some x : chToSome xs
mapChildren :: Nat a a -> Children a is -> Children a is
mapChildren f Nil = Nil
mapChildren f (x :> xs) = f x :> mapChildren f xs
mapMChildren :: Monad m => NatF m a a -> Children a is -> m (Children a is)
mapMChildren f Nil = return Nil
mapMChildren f (x :> xs) = liftM2 (:>) (f x) (mapMChildren f xs)
data Res (a :: k -> *) (i :: k) where
Res :: Children a is -> (Children a is -> a i) -> Res a i
data Some a where
Some :: a i -> Some a
class Uniplate1 (a :: k -> *) where
uniplate1 :: a i -> Res a i
data Hole a i where
Hole :: a i' -> (a i' -> a i) -> Hole a i
descend :: Uniplate1 a => Nat a a -> Nat a a
descend f a = case uniplate1 a of
Res cs wrap -> wrap (mapChildren f cs)
descendM :: (Monad m, Uniplate1 a) => NatF m a a -> NatF m a a
descendM f a = case uniplate1 a of
Res cs wrap -> liftM wrap (mapMChildren f cs)
transform :: Uniplate1 a => Nat a a -> Nat a a
transform f = f . descend (transform f)
transformM :: (Monad m, Uniplate1 a) => NatF m a a -> NatF m a a
transformM f = f <=< descendM (transformM f)
rewrite :: Uniplate1 a => NatF Maybe a a -> Nat a a
rewrite f = transform (\x -> maybe x (rewrite f) (f x))
rewriteM :: (Monad m, Uniplate1 a) => (forall i. a i -> m (Maybe (a i))) -> NatF m a a
rewriteM f = transformM (\x -> maybe (return x) (rewriteM f) =<< f x)
children :: Uniplate1 a => a i -> [Some a]
children a = case uniplate1 a of
Res cs wrap -> chToSome cs
universe :: Uniplate1 a => a i -> [Some a]
universe x = Some x : do {Some x <- children x; universe x}
holes :: Uniplate1 a => a i -> [Hole a i]
holes a = let
f :: Children a is -> (Children a is -> a i) -> [Hole a i]
f Nil wrap = []
f (c :> cs) wrap = Hole c (wrap . (:> cs)) : f cs (wrap . (c:>))
in case uniplate1 a of Res cs wrap -> f cs wrap
contexts :: Uniplate1 a => a i -> [Some (Hole a)]
contexts a = map Some hs ++ do {Hole c _ <- hs; contexts c}
where hs = holes a
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment