Skip to content

Instantly share code, notes, and snippets.

@rzeigler
Last active September 12, 2016 17:40
Show Gist options
  • Save rzeigler/e21cf0f1191f5fa38984 to your computer and use it in GitHub Desktop.
Save rzeigler/e21cf0f1191f5fa38984 to your computer and use it in GitHub Desktop.
Translation of https://github.com/tpolecat/examples/blob/master/src/main/scala/eg/FreeMonad.scala FreeMonad example to Haskell as well as an example program.
import Control.Monad.Free
import Control.Monad.State.Lazy
data TerminalOp a = ReadLine (String -> a) | WriteLine String a
instance Functor TerminalOp where
fmap f (ReadLine g) = ReadLine (f . g)
fmap f (WriteLine s a) = WriteLine s (f a)
type TerminalIO a = Free TerminalOp a
readLine :: (String -> a) -> TerminalIO a
readLine f = liftF (ReadLine f)
writeLine :: String -> TerminalIO ()
writeLine s = liftF (WriteLine s ())
toIO :: TerminalOp a -> IO a
toIO (ReadLine f) = fmap f getLine
toIO (WriteLine s a) = putStrLn s >> return a
data TermState = TermState { stdin :: [String], stdout :: [String] }
toState :: TerminalOp a -> State TermState a
toState (ReadLine f) = do
stdins <- gets stdin
stdouts <- gets stdout
put (TermState (tail stdins) stdouts)
return $ f (head stdins)
toState (WriteLine s a) = do
stdins <- gets stdin
stdouts <- gets stdout
put (TermState stdins (s : stdouts))
return a
countDown :: Int -> TerminalIO ()
countDown 1 = writeLine "1"
countDown x = writeLine (show x) >> countDown (x - 1)
program :: TerminalIO ()
program = do
s <- readLine read :: TerminalIO Int
writeLine "Tick Tock..."
countDown s
writeLine "Boom!"
stateProgram :: TermState -> TerminalIO a -> IO ()
stateProgram start prog = putStrLn "Starting State: "
>> putStrLn ("stdin: " ++ (show (stdin start))) >> putStrLn ("stdout: " ++ (show (stdout start)))
>> putStrLn "Ending State: "
>> putStrLn ("stdin: " ++ (show (stdin end))) >> putStrLn ("stdout:" ++ (show (stdout end)))
where end = snd (runState sprogram start)
sprogram = foldFree toState prog
main :: IO ()
main = putStrLn "Enter a number: "
>> (foldFree toIO program)
>> stateProgram (TermState ["2"] []) program
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment