Skip to content

Instantly share code, notes, and snippets.

@earldouglas
Last active September 14, 2016 01:56
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 earldouglas/6575d4486618c06aa04d53dafa85ee91 to your computer and use it in GitHub Desktop.
Save earldouglas/6575d4486618c06aa04d53dafa85ee91 to your computer and use it in GitHub Desktop.
{-# LANGUAGE GADTs #-}
class IOEffect x where
runIOEffect :: x a -> IO a
data M a where
Pure :: a -> M a
Ap :: M (a -> b) -> M a -> M b
Bind :: M a -> (a -> M b) -> M b
M :: IOEffect x => x a -> M a
instance Functor M where
fmap f s = Bind s (\a -> Pure $ f a)
instance Applicative M where
pure a = Pure a
(<*>) f a = Ap f a
instance Monad M where
(>>=) a mb = Bind a mb
runM :: M a -> IO a
runM (Pure a) = return a
runM (Ap f a) = (runM f) <*> (runM a)
runM (Bind s fs) = (runM s) >>= (\a -> runM (fs a))
runM (M xa) = runIOEffect xa
---
data ConsoleIO a where
WriteIO :: String -> ConsoleIO ()
ReadLineIO :: ConsoleIO String
instance IOEffect ConsoleIO where
runIOEffect (WriteIO s) = putStr s
runIOEffect ReadLineIO = getLine
---
program :: M ()
program = do
M $ WriteIO "Enter a number: "
x <- M ReadLineIO
M $ WriteIO "Enter another one: "
y <- M ReadLineIO
let z = show (read x * read y)
M $ WriteIO $ x ++ " * " ++ y ++ " = " ++ z ++ "\n"
main :: IO ()
main = runM program
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment