Hacker News new | ask | show | jobs
by okmjuhb 5661 days ago
Let's say you wanted to implement I/O in a language without side effects. You could put all your interactions with the world in a special "World" object. Every time you called world.putString("foo"), you'd get back a new world object that represents the state of the world with "foo" having been written out.

So the code (quoting from samstoke's hello world):

    main :: IO ()
    main = do
      putStrLn "Please enter your name"
      name <- getLine
      putStrLn ("Hello " ++ name ++ "!")
would get translated to:

    main :: World -> World
    main world = let newWorld = putStrLn world "Please enter your name" in
                   let (newerWorld, name) = getLine newWorld in
                     let newestWorld = putStrLn newerWorld ("Hello " ++ name ++ "!") in
                       newestWorld
Note that this makes the order of operations explicit, and that no World needs to be modified. Note also that now main has to take and return one of these World objects, so that a World needs to be threaded through all computations that will interact with the World (just like IO actions can only be executed from within other IO actions).

A monad lets you thread implicit state through a computation.