Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Haskell's monads be thought of as using and returning a hidden state parameter?

I don't understand the exact algebra and theory behind Haskell's monads. However, when I think about functional programming in general I get the impression that state would be modelled by taking an initial state and generating a copy of it to represent the next state. This is like when one list is appended to another; neither list gets modified, but a third list is created and returned.

Is it therefore valid to think of monadic operations as implicitly taking an initial state object as a parameter and implicitly returning a final state object? These state objects would be hidden so that the programmer doesn't have to worry about them and to control how they gets accessed. So, the programmer would not try to copy the object representing the IO stream as it was ten minutes ago.

In other words, if we have this code:

main = do
    putStrLn "Enter your name:"
    name <- getLine
    putStrLn ( "Hello " ++ name )

...is it OK to think of the IO monad and the "do" syntax as representing this style of code?

putStrLn :: IOState -> String -> IOState
getLine :: IOState -> (IOState, String)
main :: IOState -> IOState

-- main returns an IOState we can call "state3"
main state0 = putStrLn state2 ("Hello " ++ name)
    where (state2, name) = getLine state1
        state1 = putStrLn state0 "Enter your name:"
like image 477
AJM Avatar asked May 11 '10 22:05

AJM


1 Answers

No, that's not what monads in general do. However, your analogy is in fact exactly correct with regards to the data type State s a, which happens to be a monad. State is defined like this:

newtype State s a = State { runState :: s -> (a, s) }

...where the type variable s is the state value and a is the "regular" value that you use. So a value in "the State monad" is just a function from an initial state, to a return value and final state. The monadic style, as applied to State, does nothing more than automatically thread a state value through a sequence of functions.

The ST monad is superficially similar, but uses magic to allow computations with real side-effects, but only such that the side effects can't be observed from outside particular uses of ST.

The IO monad is essentially an ST monad set to "more magic", with side effects that touch the outside world and only a single point where IO computations are run, namely the entry point for the entire program. Still, on some conceptual level, you can still think of it as threading a "state" value through functions the way regular State does.

However, other monads don't necessarily have anything whatsoever to do with threading state, or sequencing functions, or whatnot. The operations needed for something to be a monad are incredibly general and abstract. For instance, using Maybe or Either as monads lets you use functions that might return errors, with the monadic style handling escaping from the computation when an error occurs the same way that State threads a state value. Using lists as a monad gives you nondeterminism, letting you simultaneously apply functions to multiple inputs and see all possible outputs, with the monadic style automatically applying the function to each argument and collecting all the outputs.

like image 100
C. A. McCann Avatar answered Oct 29 '22 17:10

C. A. McCann