Skip to content

Instantly share code, notes, and snippets.

@davidallsopp
Last active August 29, 2015 14:14
Show Gist options
  • Save davidallsopp/0897e25483aa1bfa6e9a to your computer and use it in GitHub Desktop.
Save davidallsopp/0897e25483aa1bfa6e9a to your computer and use it in GitHub Desktop.
Starting from the assumption of pure IO, showing that the signature of bind (>>=) arises naturally as a consequence of chaining IO values together.
module MonadicIO where
-- For pure FP, functions must be pure
-- So IO-related functions must return a value rather than having a side-effect
-- e.g. reading a line: getLine gives us an IO String (an IO that, when executed, would produce a String)
myGetLine :: IO String
myGetLine = getLine
-- e.g. writing a line: putStrLn accepts a String, and produces an IO () that, when executed, has an effect
-- and returns nothing meaningful
myPutLine :: String -> IO ()
myPutLine = putStrLn
-- so what if we want to read a line, then echo it back to the console?
-- this must have type IO ()
-- echo :: IO ()
-- echo = putStrLn getLine -- this is no good; putStrLn needs a String not an IO String
-- echo = print getLine -- nope, there's no Show instance for IO String, and it's not what we want anyway
-- we want to print the *line*, not the IO value that wraps the line
-- We need a function to glue getLine and putStrLn together.
-- It must accept IO String and String -> IO (), and return an IO (), i.e.
myBind :: IO String -> (String -> IO ()) -> IO ()
-- but this, amazingly enough, is (a specialised version of) the signature of bind (>>=)
myBind = (>>=)
-- using our illustrative functions:
echo :: IO ()
echo = myBind getLine putStrLn
-- Using the built-in >>=
echo2 :: IO ()
echo2 = getLine >>= putStrLn
-- Using do-notation
echo3 :: IO ()
echo3 = do
line <- getLine
putStrLn line
-- In reverse order using the built-in =<<
echo4 :: IO ()
echo4 = putStrLn =<< getLine
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment