# 'What exactly does "effectful" mean

Time and again I read the term *effectful*, but I am still unable to give a clear definition of what it means. I assume the correct context is effectful *computations*, but I've also seen the term effectful *values*)

I used to think that effectful means *having side effects*. But in Haskell there are no side-effects (except to some extent IO). Still there are effectful computations all over the place.

Then I read that monads are used to create effectful computations. I can somewhat understand this in the context of the `State`

Monad. But I fail to see any side-effect in the `Maybe`

monad. In general it seems to me, that Monads which wrap a function-like thing are easier to see as producing side-effects than Monads which just wrap a value.

When it comes to `Applicative`

functors I am even more lost. I always saw applicative functors as a way to `map`

a function with more than one argument. I cannot see any side-effect here. Or is there a difference between *effectful* and *with effects*?

## Solution 1:^{[1]}

A side effect is an observable interaction with its environment (apart from computing its result value). In Haskell, we try hard to avoid functions with such side effects. This even applies to `IO`

actions: when an `IO`

action is evaluated, no side effects are performed, they are executed only when the actions prescribed in the `IO`

value are executed within `main`

.

However, when working with abstractions that are related to composing computations, such as applicative functors and monads, it's convenient to somewhat distinguish between the actual value and the "rest", which we often call an "effect". In particular, if we have a type `f`

of kind `* -> *`

, then in `f a`

the `a`

part is "the value" and whatever "remains" is "the effect".

I intentionally quoted the terms, as there is no precise definition (as far as I know), it's merely a colloquial definition. In some cases there are no values at all, or multiple values. For example for `Maybe`

the "effect" is that there might be no value (and the computation is aborted), for `[]`

the "effect" is that there are multiple (or zero) values. For more complex types this distinction can be even more difficult.

The distinction between "effects" and "values" doesn't really depend on the abstraction. `Functor`

, `Applicative`

and `Monad`

just give us tools what we can do with them (`Functor`

s allow to modify values inside, `Applicative`

s allow to combine effects and `Monad`

s allow effects to depend on the previous values). But in the context of `Monad`

s, it's somewhat easier to create a mental picture of what is going on, because a monadic action can "see" the result value of the previous computation, as witnessed by the

```
(>>=) :: m a -> (a -> m b) -> m b
```

operator: The second function receives a value of type `a`

, so we can imagine "the previous computation had some effect and now there is its result value with which we can do something".

## Solution 2:^{[2]}

In support of Petr Pudlák's answer, here is an argument concerning the origin of the broader notion of "effect" espoused there.

The phrase "effectful programming" shows up in the abstract of McBride and Patterson's *Applicative Programming with Effects*, the paper which introduced applicative functors:

In this paper, we introduce

`Applicative`

functors — an abstract characterisation of an applicative style of effectful programming, weaker than`Monad`

s and hence more widespread.

"Effect" and "effectful" appear in a handful of other passages of the paper; these ocurrences are deemed unremarkable enough not to require an explicit clarification. For instance, this remark is made just after the definition of `Applicative`

is presented (p. 3):

In each example, there is a type constructor

`f`

that embeds the usual notion of value, but supports its own peculiar way of giving meaning to the usual applicative language [...] We correspondingly introduce the`Applicative`

class:[A Haskell definition of

`Applicative`

]This class generalises

SandK[i.e. the S and K combinators, which show up in the`Reader`

/function`Applicative`

instance] from threading an environment to threading an effect in general.

From these quotes, we can infer that, in this context:

Effects are the things that

`Applicative`

threads "in general".Effects are associated with the type constructors that are given

`Applicative`

instances.`Monad`

also deals with effects.

Following these leads, we can trace back this usage of "effect" back to at least Wadler's papers on monads. For instance, here is a quote from page 6 of *Monads for functional programming*:

In general, a function of type

a ? bis replaced by a function of typea ? M b. This can be read as a function that accepts an argument of typeaand returns a result of typeb, with a possible additional effect captured byM. This effect may be to act on state, generate output, raise an exception, or what have you.

And from the same paper, page 21:

If monads encapsulate effects and lists form a monad, do lists correspond to some effect? Indeed they do, and the effect they correspond to is choice. One can think of a computation of type

[a]as offering a choice of values, one for each element of the list. The monadic equivalent of a function of typea ? bis a function of typea ? [b].

The "correspond to some effect" turn of phrase here is key. It ties back to the more straightforward claim in the abstract:

Monads provide a convenient framework for simulating effects found in other languages, such as global state, exception handling, output, or non-determinism.

The pitch is that monads can be used to express things that, in "other languages", are typically encoded as side-effects -- that is, as Petr Pudlák puts it in his answer here, "an observable interaction with [a function's] environment (apart from computing its result value)". Through metonymy, that has readily led to "effect" acquiring a second meaning, broader than that of "side-effect" -- namely, whatever is introduced through a type constructor which is a `Monad`

instance. Over time, this meaning was further generalised to cover other functor classes such as `Applicative`

, as seen in McBride and Patterson's work.

In summary, I consider "effect" to have two reasonable meanings in Haskell parlance:

A "literal" or "absolute" one: an effect is a side-effect; and

A "generalised" or "relative" one: an effect is a functorial context.

On occasion, avoidable disagreements over terminology happen when each of the involved parties implicitly assumes a different meaning of "effect". Another possible point of contention involves whether it is legitimate to speak of effects when dealing with `Functor`

alone, as opposed to subclasses such as `Applicative`

or `Monad`

(I believe it is okay to do so, in agreement with Petr Pudlák's answer to *Why can applicative functors have side effects, but functors can't?*).

## Solution 3:^{[3]}

To my mind, a "side effect" is anything that a normal function couldn't do. In other words, anything in addition to just returning a value.

Consider the following code block:

```
let
y = foo x
z = bar y
in foobar z
```

This calls `foo`

, and then calls `bar`

, and then calls `foobar`

, three ordinary functions. Simple enough, right? Now consider this:

```
do
y <- foo x
z <- bar y
foobar z
```

This also calls three functions, but it also invisibly calls `(>>=)`

between each pair of lines as well. And that means that some strange things happen, depending on what type of monad the functions are running in.

If this is the identity monad, nothing special happens. The monadic version does exactly the same thing as the pure version. There are no side-effects.

If each function returns a

`Maybe`

-something, then if (say)`bar`

returns`Nothing`

, the entire code block aborts. A normal function can't do that. (I.e., in the pure version, there is*no way*to prevent`foobar`

being called.) So this version does something that the pure version cannot. Each function can return a value*or abort the block*. That's a side-effect.If each function returns a list-of-something, then the code executes for all possible combinations of results. Again, in the pure version, there is

*no way*to make any of the functions execute multiple times with different arguments. So that's a side-effect.If each function runs in a state monad, then (for example)

`foo`

can send some data directly to`foobar`

, in addition to the value you can see being passed through`bar`

. Again, you can't do that with pure functions, so that's a side-effect.In

`IO`

monad, you have all sorts of interesting effects. You can save files to disk (a file is basically a giant global variable), you can even affect code running on other computers (we call this network I/O).The

`ST`

monad is a cut-down version of the`IO`

monad. It allows mutable state, but self-contained computations cannot influence each other.The

`STM`

monad lets multiple threads talk to each other, and may cause the code to execute multiple times, and... well, you can't do any of this with normal functions.The continuation monad allows you to

*break people's minds!*Arguably that is possible with pure functions...

## Solution 4:^{[4]}

"Effect is a very vague term and that is ok because we are trying to talk about something that is outside the language. Effect and side effect are not the same thing. Effects are good. Side effects are bugs.

Their lexical similarity is really unfortunate because it leads to a lot of people conflating these ideas when they read about them and people using one instead of the other so it leads to a lot of confusion."

see here for more: https://www.slideshare.net/pjschwarz/rob-norrisfunctionalprogrammingwitheffects

## Solution 5:^{[5]}

*Functional programming context*

Effect generally means the stuff (behaviour, additional logic) that is implemented in Applicative/Monad instances.

Also, it can be said that a simple value is extended with additional behaviour.

For example,

Option models the effects of optionality

or

Option is a monad that models the effect of optionality (of being something optional)

Resources: Resource 1, Resource 2

## Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution | Source |
---|---|

Solution 1 | dfeuer |

Solution 2 | |

Solution 3 | MathematicalOrchid |

Solution 4 | Philip Schwarz |

Solution 5 |