{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-} > {-# LANGUAGE MultiParamTypeClasses #-} > module Main ( main ) where > > import Prelude hiding ( putStrLn ) > import qualified Prelude as P ( putStrLn ) > > import Data.Functor.Identity > import Control.Applicative > import Control.Monad > import Control.Monad.Trans.Class > import Control.Monad.IO.Class > import Control.Monad.State > > import Control.Monad.Shade A shade can be used to save heterogeneous types in containers with the same type e.g. using a type-class as a common denominator: > showshade :: Applicative m => Show a => a -> ShadeT m String > showshade a = pure (show a) > > hetero :: Shade String > hetero = mconcat [ showshade () , showshade 2 , showshade "hej" ] The values inside a shade are stored in a context. We can swap this context by defining a transfer function: > idToIO :: MonadIO m => Identity b -> m b > idToIO (Identity v) = putStrLn "Transferring" *> pure v The context is switched using `transfer` and we can access the value in this new context by using `shadow`: > runInIO :: MonadShade m => m Identity a -> m IO a > runInIO = transfer idToIO The point to note about this example is that the values are stored in an shades with the identity as context. We can manipulate this context including the value. We cannot, however inspect the value since it is universally quantified. > noisy :: Applicative c => String -> ShadeT c (IO ()) > noisy s = pure (putStrLn s) > collect :: Monoid s => Show s => s -> Shade (IO ()) > collect s = shade (pure (show s)) putStrLn This guy deserved a name too I feel: > perspective :: (MonadShade m, Monoid (c a)) => (a -> b) -> m c b > perspective f = shade mempty f > stuff :: IO () > stuff = join . shadow . transfer idToIO . mconcat $ > [ noisy "hej" > , noisy "med" > , noisy "dig" > , putStrLn <$> do > showshade 32 > showshade () > ] > > main :: IO () > main = do > runIdentity . shadow $ mconcat > [ collect () > , collect "hej" > ] > putStrLn :: MonadIO m => String -> m () > putStrLn = liftIO . P.putStrLn