Skip to content

Instantly share code, notes, and snippets.

@lucasdicioccio
Last active April 12, 2016 22:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucasdicioccio/7ea3f1b7548ca460fe9dc0373bf0dc58 to your computer and use it in GitHub Desktop.
Save lucasdicioccio/7ea3f1b7548ca460fe9dc0373bf0dc58 to your computer and use it in GitHub Desktop.
subtle free monads
{-# LANGUAGE DeriveFunctor #-}
module Main where
import Control.Monad.IO.Class
import Control.Monad.State
import Control.Monad.Trans.Free
data MyFunctor next = PrimitiveA next | PrimitiveB next deriving Functor
type MyFreeT m = FreeT MyFunctor m
type Program = MyFreeT (StateT Int IO)
primA = liftF (PrimitiveA ())
primB = liftF (PrimitiveB ())
-- some program built from primitives defined in MyFunctor and StateT operations
program :: Program Int
program = do
lift get >>= liftIO . putStrLn . (\n -> "a-" ++ show n)
primA
lift get >>= liftIO . putStrLn . (\n -> "b-" ++ show n)
primB
lift get >>= liftIO . putStrLn . (\n -> "c-" ++ show n)
-- returned value
lift get
-- some function to evaluate primitives at each step
step :: MonadIO m => MyFunctor (m a) -> m a
step (PrimitiveA next) = liftIO (print "primitive A") >> next
step (PrimitiveB next) = liftIO (print "primitive B") >> next
-- runs the program
example1 = runStateT (iterT step program) 0 >>= print
-- let's count every primitives
example2 = runStateT (iterT (\x -> modify (+1) >> step x) program) 0 >>= print
-- let's also count primitives
example3 = runStateT (iterT step (hoistFreeT (\x -> modify (+1) >> x) program)) 0 >>= print
main = do
print "** example-1"
example1
print "** example-2"
example2
print "** example-3"
example3
{- OUTPUT (reformatted for readability)
"** example-1" "** example-2" "** example-3"
a-0 a-0 a-1
"primitive A" "primitive A" "primitive A"
b-0 b-1 b-2
"primitive B" "primitive B" "primitive B"
c-0 c-2 c-3
(0,0) (2,2) (3,3)
Example 1 just a "control group" to ensure there is not madness.
Example 2 seems to be a post-increment:
- actually, we changed the evaluator function
Example 3 seems to be a pre-increment:
- actually, we changed the program
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment