imperative-edsl-0.4.1: src/Language/Embedded/Traversal.hs
{-# LANGUAGE CPP #-}
-- | Methods for traversing programs
module Language.Embedded.Traversal where
import Control.Monad.Operational.Higher
import Control.Monads
-- | Dry (effect-less) interpretation of an instruction. This class is like
-- 'Interp' without the monad parameter, so it cannot have different instances
-- for different monads.
class DryInterp instr
where
-- | Dry interpretation of an instruction. This function is like 'interp'
-- except that it interprets in any monad that can supply fresh variables.
dryInterp :: MonadSupply m => instr m a -> m a
-- | Interpretation of a program as a combination of dry interpretation and
-- effectful observation
observe_ :: (DryInterp instr, HFunctor instr, MonadSupply m)
=> (forall a . instr m a -> a -> m ()) -- ^ Function for observing instructions
-> Program instr a
-> m a
observe_ obs = interpretWithMonad $ \i -> do
a <- dryInterp i
obs i a
return a
-- | Interpretation of a program as a combination of dry interpretation and
-- effectful observation
observe :: (DryInterp instr, HFunctor instr, MonadSupply m)
=> (forall a . instr m a -> a -> m a) -- ^ Function for observing instructions
-> Program instr a
-> m a
observe obs = interpretWithMonad $ \i -> do
a <- dryInterp i
obs i a
instance (DryInterp i1, DryInterp i2) => DryInterp (i1 :+: i2)
where
dryInterp (Inl i) = dryInterp i
dryInterp (Inr i) = dryInterp i