9

Whenever I read about Haskell, I find that IO can cause side effects.

But I do not understand how it would do it?

Do we mean that we are writing to a file from one lazy sequence and another lazy sequence is reading from same file?

Is that the only possibility or is there something fundamentally deep?

2
  • 1
    This is a bit unclear. Do you understand how I/O causes side effects in an imperative language, e.g. C? Oct 10, 2014 at 12:36
  • ok.. I am thinking about it as you asked.. and i think i can change value of a variable when i take input in C .. that is not possible in clojure as data is immutable. Oct 10, 2014 at 12:37

6 Answers 6

16

The Haskell optimizer is allowed to freely manipulate calls to pure functions as long as the result remains the same. For example, if it can see that you are calling sqrt on the same number 100 times, it can cache the returned value and only call it once. If it can see that you never actually use the result of that function, it can choose to not call it at all.

These things can't be done with IO. If you read from stdin 100 times, you wouldn't want to optimizer to cache the first read and reuse that value 99 more times. If you write to the console and discard the return value (because you don't actually care about the return value of putStrLn) you wouldn't want the optimizer to remove the function call altogether.

That's the meaning of side effects - not from the programmer's point of view (the programmer clearly meant for these things to happen) but from the optimizer's point of view.

3
  • 2
    If one distinguishes between reading the first character from stdin vs reading the next character from stdin, then it's no different from reading from an array or list, and is totally cachable. Oct 10, 2014 at 17:36
  • But is the function call for reading the second element of an array identical to the function call that reads the first element? The function calls for reading the first character and the second character from stdin are (or at least can be) identical.
    – David K
    Oct 11, 2014 at 4:12
  • When i read your answer than i could understand answers of others. Otherwise they looked like ideal things but not motivating enough to say that Yes.. IO has side effects. so i accepted this answer. Thanks. Oct 11, 2014 at 9:28
14

Simplest possible example: printing "Hello, world!" changes the state of the system, because the console now displays "Hello, world!", and earlier it didn't. Not only have you changed the state, it's actually impossible to change it back, since you can't un-get characters from a terminal! That's about the most serious side effect possible.

4
  • do you mean haskell helps and it can remove / un-get characters..? it can not i guess.. so what ? Please do not take it as rude comment.. but i think that is the whole point of outputting.. And does programmers care if this happens.. Just for this can we not do IO from any where in the simple functions ? Oct 10, 2014 at 12:48
  • 8
    It is just the observation that output is a side effect. Oct 10, 2014 at 13:04
  • What about input? Oct 10, 2014 at 17:35
  • 4
    Consuming input is a side effect just like generating output. Before your program acted, another process might have read the secret missile treaty from the input stream. Now it no longer can, because the bytes have passed. Both actions change the state of the system in comparable ways. Oct 10, 2014 at 17:45
4

I think the problem is that you are a bit unclear on what is meant by a side effect. In a pure function with no side effects, the function gives a result that is a direct result of the input and nothing else. In a function with side effects, the function depends on or changes the state of the outside world. So if you have a function like square(x), then that is a pure function. On the other hand, if you have function like launch_the_missiles(), then that has a very real side effect (or for a more mundane example, print a page).

So doing IO changes the state of the world, that is the side effect

6
  • 5
    Actually a pure function may have some ignored side-effects: e.g., it is warming the CPU, or takes a few microsecond of time. Every physical computation have side-effects, but we (and Haskell) choose to ignore some of them! We might decide that some output is an ignorable side-effect! Oct 10, 2014 at 13:24
  • In part because you have to assume that in a lazy language that you don't always know in what order things are going to happen.
    – Zachary K
    Oct 10, 2014 at 13:26
  • @BasileStarynkevitch: Very good observation! In fact, in some contexts, the delay of a computation is considered a non-ignorable effect (that can be modelled e.g. using futures).
    – Giorgio
    Oct 10, 2014 at 17:28
  • 4
    @BasileStarynkevitch: Languages exist outside of implementations. The language does not concern itself with CPUs and stuff. Haskell (the language) is not choosing to ignore said side effects because there aren't any in Language Heaven. (Related: Haskell is Turing complete, but no implementation could ever be). Oct 10, 2014 at 20:37
  • @ThomasEding: A programming language is an abstraction that captures some aspects of a real-world computation while ignoring others. Which one are ignored by a language is a design decision. Haskell ignores side-effects like the time needed for evaluating an expression. This may seem a quite obvious design decision, but it still is a decision.
    – Giorgio
    Oct 11, 2014 at 9:00
2

It sounds like you don't know the CS definition of a side effect. A function has a side effect if it has any observable interaction with the system outside of that function. Therefore output is always a side effect, you can observe a change in the hard drive, network, console where ever your output went. Input is similarly a side effect, because it has an effect on the computation happening in the function, and may cause an effect in the external system i.e. reading from a console or socket.

1

Side effects mean that, after every IO operation, the state of the system may be changed. Haskell provides a clear divide pure Haskell code and IO code.

See : http://learnyouahaskell.com/input-and-output#hello-world ;

from the book: "In Haskell, a function can't change some state, like changing the contents of a variable (when a function changes state, we say that the function has side-effects). "

0

Did you ever hear this aphorism?

No man can step in the same river twice. For the second time, it is not the same river, and he is not the same man.

Imagine one of your functions writes a 1 to /dev/ttyusb0. In UNIX, this is "just a file", but in real life, this is actually the name of a microcontroller, and by writing a 1 it activates a bread-slicing machine and slices 500 loaves of pumpernickel. Writing a 1 the first time caused 500 loaves of pumpernickel to go from the "unsliced" state to the "sliced" state. Sending another 1 does not have this effect (because you can't go back to "unsliced"!). It's not the same river.

Imagine another of your functions reads some data from a stream. If it was a static file perhaps you could read it twice and get the same results, but if instead your stream is a data buffer from (yet another) microcontroller (this one is monitoring the baking temperature), then reading the value over and over again will give different results as the oven heats up or cools down. He's not the same man.

0

Not the answer you're looking for? Browse other questions tagged or ask your own question.