Hans van Thiel wrote:
I just saw somewhere that one of the purposes of monads is to capture
side effects.

There are a few things that have "side effects". The best way to capture this is to see that there are both
  (1) commands whose result depends on some external state
  (2) commands which alter that state

The (2) group has side effects, and (1) is affected by them. The order in which (1) and (2) are performed matters.

commands that evaluate to different things based on environment/history/input:
  * reading from memory location or reference
  * reading from a file or network stream or sensor (e.g. keyboard or mouse)
  * a random or pseudo-random number generator

commands which affect the environment
  * writing to a memory location or reference
  * writing to a file or network
  * changing the display buffer (i.e. windows on the screen)

command which are both (1) and (2), often because they might fail:
  * creating or deleting a file
  * obtaining a lock or semaphore
  * interacting with a message queue

So allocating a mutable variable and writing to it are side-effect operations which have to be carefully ordered with the corresponding reads.

Things without side effects are the immutable bindings produced by "let/where", and application of functions. This is independent of being lazy or strict.

Note that "putStr :: String -> IO ()" is a function, and as such it is a pure value. "putString ['a','b','\n']" is a pure value of "IO ()". Performing this command in the IO monad has side effects.

The fact that functions like putStr and things with types of "IO ()" are pure value means that they can be produced and passed around is powerful way of working. It is possible to create objects in C++/Java which encapsulate an operation, but it takes more syntax.

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to