module Ermine.Syntax.Scope
( hoistScope
, bitraverseScope
, transverseScope
, BoundBy(..)
, instantiateVars
, serializeScope3
, deserializeScope3
, mergeScope
, splitScope
, rebind
, inScope
, _Scope
) where
import Bound
import Bound.Scope
import Bound.Var
import Control.Applicative
import Control.Lens
import Control.Monad (liftM)
import Control.Monad.Trans
import Data.Bytes.Serial
import Data.Bytes.Get
import Data.Bytes.Put
class Monad m => BoundBy tm m | tm -> m where
boundBy :: (a -> m b) -> tm a -> tm b
instance Monad m => BoundBy (Scope b m) m where
boundBy = flip (>>>=)
serializeScope3 :: MonadPut m
=> (b -> m ()) -> (forall a. (a -> m ()) -> f a -> m ()) -> (v -> m ())
-> Scope b f v -> m ()
serializeScope3 pb pf pv (Scope e) = pf (serializeWith2 pb (pf pv)) e
deserializeScope3 :: MonadGet m
=> m b -> (forall a. m a -> m (f a)) -> m v
-> m (Scope b f v)
deserializeScope3 gb gf gv = Scope <$> gf (deserializeWith2 gb (gf gv))
mergeScope :: Monad c => Scope b1 (Scope b2 c) a -> Scope (Var b1 b2) c a
mergeScope = toScope . liftM go . fromScope . fromScope where
go (B b2) = B (F b2)
go (F (B b1)) = B (B b1)
go (F (F a)) = F a
splitScope :: (Applicative c, Monad c)
=> Scope (Var b1 b2) c a -> Scope b1 (Scope b2 c) a
splitScope (Scope e) = Scope . lift $ swizzle <$> e
where
swizzle (B (B b1)) = B b1
swizzle (B (F b2)) = F . Scope . pure . B $ b2
swizzle (F a) = F $ lift a
rebind :: Functor f => (b -> Var b' (f a)) -> Scope b f a -> Scope b' f a
rebind f = Scope . fmap (unvar f F) . unscope
inScope :: (Functor f, Monad t)
=> (t (Var b a) -> f (t (Var b a))) -> Scope b t a -> f (Scope b t a)
inScope action = fmap toScope . action . fromScope
_Scope :: Iso (Scope b f a) (Scope b' f' a') (f (Var b (f a))) (f' (Var b' (f' a')))
_Scope = iso unscope Scope