What are side effects in Haskell?

Hello All, I just saw somewhere that one of the purposes of monads is to capture side effects. I understand what a side effect is in C, for example. Say you want to switch the contents of two variables. Then you need a third temporary variable to store an intermediate result. If this is global, then it will be changed by the operation. But what is a side effect in an fp language like Haskell? As a follow up, I understand why an IO action like getLine or getChar is not a function; its results can be different for different calls. But why not have something like getChar c or getLine str? The types of c or str are pretty clear, aren't they? Just something that's been puzzling me for some time now...thanks. Regards, Hans van Thiel

On Tue, Dec 23, 2008 at 3:16 PM, Hans van Thiel
Hello All,
I just saw somewhere that one of the purposes of monads is to capture side effects. I understand what a side effect is in C, for example. Say you want to switch the contents of two variables. Then you need a third temporary variable to store an intermediate result. If this is global, then it will be changed by the operation. But what is a side effect in an fp language like Haskell?
Generally speaking, you have no side effects whenever the only result of a function is the return of its outcome, in contrast with those changing something else (like updating a database, a file, the screen output and so on). In Haskell you can't write an effectful function because its scope is limited to the function's local bindings (i.e. its input arguments and any other name locally defined in its definition). If you want something "global" to affect a function's operations you have to pass it, either explicitly (pure functions) or implicitly (monadic actions). Likewise, if you want to persist an effect after a function's execution you have to gather it from the returned value and feed it to any other subsequent function calls. Though, notice that there are exceptions to the above rule (namely unsafePerformIO) but they are kind of tricks.
As a follow up, I understand why an IO action like getLine or getChar is not a function; its results can be different for different calls.
Anything in Haskell is a function: getLine and getChar ARE functions returning actions to be executed in the IO Monad, i.e. at run-time.
But why not have something like getChar c or getLine str? The types of c or str are pretty clear, aren't they?
Because c are not effected by getChar or getLine, as they are outside the scope of the functions. What you are really passing to getChar/getLine is just the content of c and str which goes out of the scope just after the functions have finished executing. Hope this helps. Cristiano

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.

Am 23.12.2008 um 15:16 schrieb Hans van Thiel:
Hello All,
I just saw somewhere that one of the purposes of monads is to capture side effects. I understand what a side effect is in C, for example. Say you want to switch the contents of two variables. Then you need a third temporary variable to store an intermediate result. If this is global, then it will be changed by the operation.
But the two variables have also changed. After all they have different values after the switch. You see, even locally changing a variable is a side-effect. It changes the state of the program. Pure Haskell programs on the other hand have no notion of state, there are no variables which can change their value. Every time you want to manipulate something you're actually generating an new copy. You mustn't think of a haskell program as a series of changes to some state. However when you *do* want state you can simulate it with a monad. The IO Monad is a special case here, since its actions don't change your program, they change the "world" the program is running in (writing files etc.). getLine etc are functions when you think of them as taking a hidden parameter, the state of the world. So getChar would become getChar :: World -> (Char,World) but the world stays hidden inside the IO Monad. Regards, Adrian

Using GHCi I found it informative to see that IO indeed is a kind of state
monad. Here's a GHCi session to show that:
Prelude> :m GHC.Prim
Prelude GHC.Prim> :i IO
newtype IO a
= GHC.IOBase.IO (State# RealWorld -> (# State# RealWorld, a #))
-- Defined in GHC.IOBase
instance Monad IO -- Defined in GHC.IOBase
instance Functor IO -- Defined in GHC.IOBase
So every "IO a" action takes the RealWorld as input, and outputs
the RealWorld and some extra value "a" :)
2008/12/23 Adrian Neumann
Am 23.12.2008 um 15:16 schrieb Hans van Thiel:
Hello All,
I just saw somewhere that one of the purposes of monads is to capture side effects. I understand what a side effect is in C, for example. Say you want to switch the contents of two variables. Then you need a third temporary variable to store an intermediate result. If this is global, then it will be changed by the operation.
But the two variables have also changed. After all they have different values after the switch. You see, even locally changing a variable is a side-effect. It changes the state of the program. Pure Haskell programs on the other hand have no notion of state, there are no variables which can change their value. Every time you want to manipulate something you're actually generating an new copy. You mustn't think of a haskell program as a series of changes to some state.
However when you *do* want state you can simulate it with a monad. The IO Monad is a special case here, since its actions don't change your program, they change the "world" the program is running in (writing files etc.). getLine etc are functions when you think of them as taking a hidden parameter, the state of the world. So getChar would become
getChar :: World -> (Char,World)
but the world stays hidden inside the IO Monad.
Regards,
Adrian
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Fri, 2008-12-26 at 15:38 +0100, Peter Verswyvelen wrote:
Using GHCi I found it informative to see that IO indeed is a kind of state monad. Here's a GHCi session to show that:
Prelude> :m GHC.Prim Prelude GHC.Prim> :i IO newtype IO a = GHC.IOBase.IO (State# RealWorld -> (# State# RealWorld, a #)) -- Defined in GHC.IOBase instance Monad IO -- Defined in GHC.IOBase instance Functor IO -- Defined in GHC.IOBase
So every "IO a" action takes the RealWorld as input, and outputs the RealWorld and some extra value "a" :) [snip]
Thanks to all who've replied! So, the way I get it, everything in Haskell is a function, including IO. Moreover, there exist mathematical foundations for what functions are, in set theory and, more modern, more expressive, in category theory. However, some functions in Haskell may have side effects, like printing something on the screen, updating a database, or producing a random number. These functions are called 'actions' in Haskell. Now I'm starting to guess... There is no mathematical foundation for these side effects (likewise for persistent data), yet they are needed sometimes. However, there is a mechanism (sometimes) to compose functions using an extra type m a, m b, m c etc. instead of types a, b, c... This does not solve the problem concerning side effects, but it does provide a sort of 'Chinese boxes' to contain them within these type constructors m. Moreover, in the case of the type designation 'IO ...', you can't get anything out of the box. So now, at least, you've got a clean interface between the parts of your program which do not involve side effects, and the 'actions'. If I guess correctly, then the general statement 'monads are for actions' is wrong. It should be something like, 'monadic composition is a useful method of generalization, which, by the way, allows you to isolate side effects in a controlled manner'. Regards, Hans van Thiel

Hans van Thiel wrote:
However, some functions in Haskell may have side effects, like printing something on the screen, updating a database, or producing a random number. These functions are called 'actions' in Haskell.
Not really true (disregarding things like unsafePerformIO). I haven't been following this thread, so I don't know if anybody else has suggested this, but perhaps it would be helpful to distinguish between evaluating expressions and performing actions. Evaluation is simply graph reduction, which is Haskell's only method of computation. There are no side-effects when you evaluate an expression (again, disregarding unsafePerformIO and company), even if that expression evaluates to an IO action. To perform an action is to cause the side-effect which that action represents. *You* never perform an action in Haskell. The runtime does. All you do is say how to evaluate those actions. Essentially, what the IO monad does is give you a DSL for constructing (by evaluation) effectful, imperative programs at runtime. The runtime will cause your program to evaluate the next action, then perform it, then cause your program to evaluate the next action, then perform it, and so on. At no point is the purity of your program broken by this.
However, there is a mechanism (sometimes) to compose functions using an extra type m a, m b, m c etc. instead of types a, b, c... This does not solve the problem concerning side effects, but it does provide a sort of 'Chinese boxes' to contain them within these type constructors m. Moreover, in the case of the type designation 'IO ...', you can't get anything out of the box. So now, at least, you've got a clean interface between the parts of your program which do not involve side effects, and the 'actions'.
This is another way to think of it. It is how I first thought of IO before I discovered the way I described above. It's a pretty good metaphor, and I don't think it's harmful, so you can stick with it for now if you would prefer.
If I guess correctly, then the general statement 'monads are for actions' is wrong. It should be something like, 'monadic composition is a useful method of generalization, which, by the way, allows you to isolate side effects in a controlled manner'.
Right on. Monads are extremely useful for things that don't involve side-effects. Hope this helps, - Jake

On Sat, 2008-12-27 at 11:54 -0600, Jake McArthur wrote:
Hans van Thiel wrote:
However, some functions in Haskell may have side effects, like printing something on the screen, updating a database, or producing a random number. These functions are called 'actions' in Haskell.
Not really true (disregarding things like unsafePerformIO). I haven't been following this thread, so I don't know if anybody else has suggested this, but perhaps it would be helpful to distinguish between evaluating expressions and performing actions.
Evaluation is simply graph reduction, which is Haskell's only method of computation. There are no side-effects when you evaluate an expression (again, disregarding unsafePerformIO and company), even if that expression evaluates to an IO action.
To perform an action is to cause the side-effect which that action represents. *You* never perform an action in Haskell. The runtime does. All you do is say how to evaluate those actions.
Essentially, what the IO monad does is give you a DSL for constructing (by evaluation) effectful, imperative programs at runtime. The runtime will cause your program to evaluate the next action, then perform it, then cause your program to evaluate the next action, then perform it, and so on. At no point is the purity of your program broken by this.
[snip] I'm starting to understand it now...thanks again to everybody for all the helpful replies! Best regards, Hans van Thiel

On Sat, Dec 27, 2008 at 4:50 PM, Hans van Thiel
However, some functions in Haskell may have side effects, like printing something on the screen, updating a database, or producing a random number. These functions are called 'actions' in Haskell.
No :D I'll try to explain using the same picture that came into my mind when I first got what monads really are... Everything in Haskell is a function AND an Haskell function is always pure, i.e. has no side effects. Functions may return "actions", which are a special kind of value even though they are no different to Haskell from values of any other type. When you are returning an action is like when you go to a driver and give him a car: the driver takes the car you gave him and takes it wherever the car is supposed to go. You build the car using small pieces (i.e. basic functions returning actions like putStrLn) and putting everything together using combinators (like >>= and >> or the "do" notation). So, the car in the example is an "action" (or, more formally, a value in a monad). Your Haskell functions (like putStrLn or anything) just return the car, but they don't run it: they are run at run-time by the Haskell run-time environment whose only task is to run values in the IO Monad, i.e. running the car. Even it may not be apparent for the IO Monad, every Monad value is run at some point in time: almost every monad is associated to at least a function running the monad: for the State Monad this is runState, for the Reader Monad is runReader and so on. The only exception to this is the IO Moand, which can be run only by the Haskell run time, implicitly: this is the reason why you'll never see a "runIO" thing. When the monad is run, it generate side-effects, like printing to screen, opening file and so on. If you're used to Unix administration, another image to understand monads are scripts. Haskell functions return script files that are run by the shell to affect the system they are run on. In the end, they are small pieces (the basic commands present in the system) put together by bash constructs, like "for", "while" and so on. Hope this helps. -- Cristiano

On 2008 Dec 27, at 15:16, Cristiano Paris wrote:
On Sat, Dec 27, 2008 at 4:50 PM, Hans van Thiel
wrote: However, some functions in Haskell may have side effects, like printing something on the screen, updating a database, or producing a random number. These functions are called 'actions' in Haskell.
Functions may return "actions", which are a special kind of value even though they are no different to Haskell from values of any other type.
There is another way to think about it (which happens to also be the way GHC implements it): an "action" is just a partially applied function. In the case of IO, the missing value is the state, which has the opaque internal type RealWorld# that can't normally be instantiated. (unsafePerformIO works by using an internal function which synthesizes a value of type RealWorld#. Since all the IO code *and* the code generator in GHC assume this can't be done, unsafePerformIO is capable of confusing things rather badly. In particular, you need to tell GHC to inline any code using unsafePerformIO because otherwise it can make incorrect assumptions and very strange behavior will result. UnsafeInterleaveIO is even sneakier: it clones the hidden RealWorld# value, which brings its own kinds of confusion into the mix.) In the normal course of events, your program becomes a long chain of unapplied functions (think foo. bar . baz . (...)), waiting for something to inject a RealWorld# into it. This is the value of "main". Conceptually, the runtime then injects a RealWorld# and the program runs. (In reality, GHC knows that code doesn't actually have to be generated to carry RealWorld# values around, so the generated program ends up looking more or less normal.) -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Everything in Haskell is a function [...]
Where did this idea come from?
I'd say every expression in Haskell denotes a pure value, only some of which
are functions (have type a->b for some types a & b).
- Conal
On Sat, Dec 27, 2008 at 12:16 PM, Cristiano Paris
On Sat, Dec 27, 2008 at 4:50 PM, Hans van Thiel
wrote: However, some functions in Haskell may have side effects, like printing something on the screen, updating a database, or producing a random number. These functions are called 'actions' in Haskell.
No :D I'll try to explain using the same picture that came into my mind when I first got what monads really are...
Everything in Haskell is a function AND an Haskell function is always pure, i.e. has no side effects.
Functions may return "actions", which are a special kind of value even though they are no different to Haskell from values of any other type.
When you are returning an action is like when you go to a driver and give him a car: the driver takes the car you gave him and takes it wherever the car is supposed to go. You build the car using small pieces (i.e. basic functions returning actions like putStrLn) and putting everything together using combinators (like >>= and >> or the "do" notation).
So, the car in the example is an "action" (or, more formally, a value in a monad). Your Haskell functions (like putStrLn or anything) just return the car, but they don't run it: they are run at run-time by the Haskell run-time environment whose only task is to run values in the IO Monad, i.e. running the car.
Even it may not be apparent for the IO Monad, every Monad value is run at some point in time: almost every monad is associated to at least a function running the monad: for the State Monad this is runState, for the Reader Monad is runReader and so on.
The only exception to this is the IO Moand, which can be run only by the Haskell run time, implicitly: this is the reason why you'll never see a "runIO" thing.
When the monad is run, it generate side-effects, like printing to screen, opening file and so on.
If you're used to Unix administration, another image to understand monads are scripts. Haskell functions return script files that are run by the shell to affect the system they are run on. In the end, they are small pieces (the basic commands present in the system) put together by bash constructs, like "for", "while" and so on.
Hope this helps.
-- Cristiano _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, Dec 30, 2008 at 8:35 AM, Conal Elliott
Everything in Haskell is a function [...]
Where did this idea come from?
I'd say every expression in Haskell denotes a pure value, only some of which are functions (have type a->b for some types a & b).
Maybe more formally correct, but my statement still holds true as any values can be tought as constant functions, even those representing functions themselves. Cristiano

On Fri, Jan 2, 2009 at 2:52 AM, Cristiano Paris
On Tue, Dec 30, 2008 at 8:35 AM, Conal Elliott
wrote: Everything in Haskell is a function [...]
Where did this idea come from?
I'd say every expression in Haskell denotes a pure value, only some of which are functions (have type a->b for some types a & b).
Maybe more formally correct, but my statement still holds true as any values can be tought as constant functions, even those representing functions themselves.
Cristiano
I think most of the introductory material I've seen that made me go "aha now I get it" say pure functional programming is about values, and transformations of those values, and that functions are also values. Then they usually go into admitting that that's only really good for heating up the CPU and that I/O and side-effects have to be made possible, but they're not willing to give up what they won for us by having everything be a value... then monads enter the discussion or "actions", and then monads get introduced later. Dave
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

"David Leimbach"
I think most of the introductory material I've seen that made me go "aha now I get it" say pure functional programming is about values,
I dare to claim that functional programming is all about lambdas and reduction, and that functions and values are just two names for the same thing... in the same way that there are words for square and cube, but only one word to sum up all (n-dimensional) hypercubes. -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited.

Hi Cristiano,
Similarly, any value can be thought of as a list (perhaps singleton), a
Maybe (Just), a pair ((,) undefined or (,) mempty), an IO (return), ... (any
Applicative).
And yet I've heard "everything is a function" on several occasions, but not
these others. Hence my (continuing) puzzlement about the source of that
idea. I have some speculations:
* In pure "OO" programming, everything is an object, so in pure "functional"
programming, one might assume everything is a function. I find the term
"value-oriented programming" a more accurate label than "functional
programming".
* C has definitions for functions but assignments for other types. Since
pure functional languages eliminate assignment, one might assume that only
functions remain. (I also hear people refer to top-level definitions in a
Haskell module as "functions", whether they're of function type or not.)
Are there other thoughts & insights about the source of the idea that
"everything is a function"?
Thanks,
- Conal
On Fri, Jan 2, 2009 at 2:52 AM, Cristiano Paris
On Tue, Dec 30, 2008 at 8:35 AM, Conal Elliott
wrote: Everything in Haskell is a function [...]
Where did this idea come from?
I'd say every expression in Haskell denotes a pure value, only some of which are functions (have type a->b for some types a & b).
Maybe more formally correct, but my statement still holds true as any values can be tought as constant functions, even those representing functions themselves.
Cristiano

On Fri, Jan 2, 2009 at 8:53 PM, Conal Elliott
I have some speculations:
* In pure "OO" programming, everything is an object, so in pure "functional" programming, one might assume everything is a function. I find the term "value-oriented programming" a more accurate label than "functional programming".
First, I've to say that I'm not a language theorist in any way. That said, I think yours is indeed a good point, yet programs in Haskell are *strictly* expressed in terms of function applications, in contrast to other languages where programs are made up *mostly* of function invocations and other effectful statements, like assignments and IO. The fact that functions are values like any others is, at the same time, the beauty and the power of the functional paradigm. Cristiano

Granting the "everything is a function" idea the best intent, maybe what it's trying to express is the related but different notion that everything *can be* a function -- i.e. that any value can be replaced by a function which yields a value of the appropriate type. Alternately, it could be a confusion between the untyped lambda calculus, in which everything really is a function, and the typed lambda calculus, in which things are more complicated? --S. On Jan 2, 2009, at 2:53 PM, Conal Elliott wrote:
Hi Cristiano,
Similarly, any value can be thought of as a list (perhaps singleton), a Maybe (Just), a pair ((,) undefined or (,) mempty), an IO (return), ... (any Applicative).
And yet I've heard "everything is a function" on several occasions, but not these others. Hence my (continuing) puzzlement about the source of that idea. I have some speculations:
* In pure "OO" programming, everything is an object, so in pure "functional" programming, one might assume everything is a function. I find the term "value-oriented programming" a more accurate label than "functional programming".
* C has definitions for functions but assignments for other types. Since pure functional languages eliminate assignment, one might assume that only functions remain. (I also hear people refer to top-level definitions in a Haskell module as "functions", whether they're of function type or not.)
Are there other thoughts & insights about the source of the idea that "everything is a function"?
Thanks,
- Conal
On Fri, Jan 2, 2009 at 2:52 AM, Cristiano Paris
wrote: On Tue, Dec 30, 2008 at 8:35 AM, Conal Elliott wrote: Everything in Haskell is a function [...]
Where did this idea come from?
I'd say every expression in Haskell denotes a pure value, only some of which are functions (have type a->b for some types a & b).
Maybe more formally correct, but my statement still holds true as any values can be tought as constant functions, even those representing functions themselves.
Cristiano
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

2009/1/3 Conal Elliott
Are there other thoughts & insights about the source of the idea that "everything is a function"?
Lazy evaluation can make values seem like functions, given that laziness can be modeled in a strict imperative language by 0-argument functions. Also, in an uncurried language, decreasing the number of arguments to a function, still keeps it a function, eg foo(int a, int b); // 2 arguments foo(int a); // 1 argument foo(); // 0 arguments, but still a function In a strict language, there is a distinction between 0-argument functions and values; there isn't in Haskell, but it is still nice to maintain the idea of "0-argument functions" in Haskell -- which are just values. Cheers, Reiner

"Reiner Pope"
2009/1/3 Conal Elliott
: Are there other thoughts & insights about the source of the idea that "everything is a function"?
Lazy evaluation can make values seem like functions, given that laziness can be modeled in a strict imperative language by 0-argument functions.
Also, in an uncurried language, decreasing the number of arguments to a function, still keeps it a function, eg foo(int a, int b); // 2 arguments foo(int a); // 1 argument foo(); // 0 arguments, but still a function In a strict language, there is a distinction between 0-argument functions and values; there isn't in Haskell, but it is still nice to maintain the idea of "0-argument functions" in Haskell -- which are just values.
You can factor a cool intuitive understanding about IO actions not being the action itself, but just tokens that represent an action, out of this, by adding just one sentence. I guess the proper way to offset functions and values depends on what you want to explain, and multiple views on the same thing can't hurt. Conal, you aren't interrogating the list to figure out how to write a Haskell version of the wizard book, are you? We'd have to stop the pizza deliveries if you stop working on reactive... ;) -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited.

Hans van Thiel wrote:
However, there is a mechanism (sometimes) to compose functions using an extra type m a, m b, m c etc. instead of types a, b, c... This does not solve the problem concerning side effects, but it does provide a sort of 'Chinese boxes' to contain them within these type constructors m. Moreover, in the case of the type designation 'IO ...', you can't get anything out of the box. So now, at least, you've got a clean interface between the parts of your program which do not involve side effects, and the 'actions'.
The monad abstraction is exactly these sort of chinese boxes (though IO in particular can more fruitfully be thought of as a partially applied function, as Brandon Allbery says). The trick is in asking how these chinese boxes work. Operations in category theory are often described as "structure preserving", so what is the structure of a monad and how is it preserved? In general we can think of a monadic value, ma :: M A, as an M-shaped box with some number of A-shaped holes in it, which are filled by A-shaped things--- like swiss cheese where the holes are filled with red marbles. When the bind operator, (>>= f), is applied we first replace each red marble, a :: A, with a hunk of swiss cheese filled by blue marbles, (f a) :: M B; the bind operator then converts the M(M B) into M B while "preserving the structure" of both the inner and outer Ms. With the swiss cheese visualization in mind, what is that structure? Each of the holes has some kind of index or path, some way of distinguishing it from all of the other holes. Moreover, these indexes have some sort of local or hierarchical structure such that the M(M B) -> M B conversion does not disturb the inner and outer indices when it concatenates them together. The question then is what do these indices look like? And that is where every monad is different and where the monad hides side effects. Some monads don't have side effects, like lists which are indexed by their position in sequence. Side effects are what happens when you traverse from one marble to the next. For IO, the side effect *is* the index by which we can reach that value. For other monads it's a combination of side effects and something more tangible. It's possible to give a recipe without baking a cake, or to give directions without walking there yourself. You can take the functions f :: A -> M B and g :: B -> M C, and combine them to get (f >=> g) :: A -> M C even without knowing which A will be passed in, and hence which M B we're preserving the structure of. Because we do not need to *perform* side-effecting actions in order to say "do this, then do that" or "go here, then go there" we can purely do whatever we like when constructing these monadic values. Constructing these recipes, like a partially applied function, does nothing in itself. In the end you have a recipe or a new function to use. According to the monadic formalism, we can always take marbles and wrap them up in swiss cheese, but we can never get rid of the swiss cheese and get our marbles back. This is only a half truth. Somehow, for every monad, we can escape. The problem is that, because every monad is different, we escape from each of them differently and so there is no single generic method of escape that works for all of them. This is easy to see since different monads can have different numbers of holes in them. Which one do we return when they all have different ways of indexing the options? How do we combine them if we want to return more than one? What if there aren't any? Even for a single monad there can be more than one way to escape. For concrete monads like list, Maybe, (Either a),... the "running" functions just amount to choosing to interpret them as an algebraic data type instead. For functional monads like Reader, Writer, State, (e->),... the "running" function again simply chooses to interpret them as functions instead of as monads. The ST monad is just another functional monad, but with some extra magic that allows it to have localized side-effects that can't be seen from the outside. The IO monad is much like the ST monad, except that there's no way to contain the side effects when you "run" it. For this reason there is no pure function which extracts a value from IO. That function would be called running the program. -- Live well, ~wren

Adrian Neumann
Am 23.12.2008 um 15:16 schrieb Hans van Thiel:
I just saw somewhere that one of the purposes of monads is to capture side effects. I understand what a side effect is in C, for example. Say you want to switch the contents of two variables. Then you need a third temporary variable to store an intermediate result. If this is global, then it will be changed by the operation.
[...]
However when you *do* want state you can simulate it with a monad. The IO Monad is a special case here, since its actions don't change your program, they change the "world" the program is running in (writing files etc.). getLine etc are functions when you think of them as taking a hidden parameter, the state of the world. So getChar would become
getChar :: World -> (Char,World)
but the world stays hidden inside the IO Monad.
Yes, I like this view, but you shouldn't say that the world is hidden inside the IO monad, because you can easily use part of that state in computations. In my view, the IO monad is some notion of this: type IO = State World The main difference between this and the real IO is that there is no value for the (entire) world's state you could refer to, which eliminates the need for 'get', 'put', and by introducing a 'main' computation, also 'runState' becomes unnecessary. In fact, this makes the whole 'World' type unnecessary. So IO is really just a theoretical construct to make input/output consistent with referential transparency. This is a very short version of what I have written in section 7 [1] of my monads tutorial. [1] http://ertes.de/articles/monads.html#section-7 Greets, Ertugrul. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/
participants (15)
-
Achim Schneider
-
Adrian Neumann
-
Brandon S. Allbery KF8NH
-
ChrisK
-
Conal Elliott
-
Cristiano Paris
-
Cristiano Paris
-
David Leimbach
-
Ertugrul Soeylemez
-
Hans van Thiel
-
Jake McArthur
-
Peter Verswyvelen
-
Reiner Pope
-
Sterling Clover
-
wren ng thornton