Last active
August 29, 2015 14:05
-
-
Save AndrasKovacs/2732f0432ec50500d880 to your computer and use it in GitHub Desktop.
Two flavors of uniplate for indexed types.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 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