What exactly does “effectful” mean












24















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?










share|improve this question

























  • Maybe useful: slpopejoy.github.io/posts/Effectful01.html He defines effectful as: 1. Actual side-effects (IO) 2. Stuff that seems like side-effects (State, Writer, etc.) 3. Contexts that persist over function calls (Reader, State, etc.) 4. Non-local control flow (Maybe, Either).

    – T.J. Crowder
    Oct 28 '15 at 8:59






  • 3





    Most monads are defined in terms of pure computation, but from a programmer's point of view it is common to think to State s a as an imperative-like subroutine that can read/write the state s with side-effects and finally produce an a. Even if it is pure, sometimes it is convenient to pretend it's not. On topic, I'd say that effectful and with effects mean the same thing, even if they are sometimes applied broadly to values wrapped in any monad/applicative, even when those do not model side effects.

    – chi
    Oct 28 '15 at 9:18
















24















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?










share|improve this question

























  • Maybe useful: slpopejoy.github.io/posts/Effectful01.html He defines effectful as: 1. Actual side-effects (IO) 2. Stuff that seems like side-effects (State, Writer, etc.) 3. Contexts that persist over function calls (Reader, State, etc.) 4. Non-local control flow (Maybe, Either).

    – T.J. Crowder
    Oct 28 '15 at 8:59






  • 3





    Most monads are defined in terms of pure computation, but from a programmer's point of view it is common to think to State s a as an imperative-like subroutine that can read/write the state s with side-effects and finally produce an a. Even if it is pure, sometimes it is convenient to pretend it's not. On topic, I'd say that effectful and with effects mean the same thing, even if they are sometimes applied broadly to values wrapped in any monad/applicative, even when those do not model side effects.

    – chi
    Oct 28 '15 at 9:18














24












24








24


10






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?










share|improve this question
















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?







haskell monads applicative side-effects






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 6 '18 at 13:54









duplode

23k44885




23k44885










asked Oct 28 '15 at 8:55









Martin DrautzburgMartin Drautzburg

2,7441331




2,7441331













  • Maybe useful: slpopejoy.github.io/posts/Effectful01.html He defines effectful as: 1. Actual side-effects (IO) 2. Stuff that seems like side-effects (State, Writer, etc.) 3. Contexts that persist over function calls (Reader, State, etc.) 4. Non-local control flow (Maybe, Either).

    – T.J. Crowder
    Oct 28 '15 at 8:59






  • 3





    Most monads are defined in terms of pure computation, but from a programmer's point of view it is common to think to State s a as an imperative-like subroutine that can read/write the state s with side-effects and finally produce an a. Even if it is pure, sometimes it is convenient to pretend it's not. On topic, I'd say that effectful and with effects mean the same thing, even if they are sometimes applied broadly to values wrapped in any monad/applicative, even when those do not model side effects.

    – chi
    Oct 28 '15 at 9:18



















  • Maybe useful: slpopejoy.github.io/posts/Effectful01.html He defines effectful as: 1. Actual side-effects (IO) 2. Stuff that seems like side-effects (State, Writer, etc.) 3. Contexts that persist over function calls (Reader, State, etc.) 4. Non-local control flow (Maybe, Either).

    – T.J. Crowder
    Oct 28 '15 at 8:59






  • 3





    Most monads are defined in terms of pure computation, but from a programmer's point of view it is common to think to State s a as an imperative-like subroutine that can read/write the state s with side-effects and finally produce an a. Even if it is pure, sometimes it is convenient to pretend it's not. On topic, I'd say that effectful and with effects mean the same thing, even if they are sometimes applied broadly to values wrapped in any monad/applicative, even when those do not model side effects.

    – chi
    Oct 28 '15 at 9:18

















Maybe useful: slpopejoy.github.io/posts/Effectful01.html He defines effectful as: 1. Actual side-effects (IO) 2. Stuff that seems like side-effects (State, Writer, etc.) 3. Contexts that persist over function calls (Reader, State, etc.) 4. Non-local control flow (Maybe, Either).

– T.J. Crowder
Oct 28 '15 at 8:59





Maybe useful: slpopejoy.github.io/posts/Effectful01.html He defines effectful as: 1. Actual side-effects (IO) 2. Stuff that seems like side-effects (State, Writer, etc.) 3. Contexts that persist over function calls (Reader, State, etc.) 4. Non-local control flow (Maybe, Either).

– T.J. Crowder
Oct 28 '15 at 8:59




3




3





Most monads are defined in terms of pure computation, but from a programmer's point of view it is common to think to State s a as an imperative-like subroutine that can read/write the state s with side-effects and finally produce an a. Even if it is pure, sometimes it is convenient to pretend it's not. On topic, I'd say that effectful and with effects mean the same thing, even if they are sometimes applied broadly to values wrapped in any monad/applicative, even when those do not model side effects.

– chi
Oct 28 '15 at 9:18





Most monads are defined in terms of pure computation, but from a programmer's point of view it is common to think to State s a as an imperative-like subroutine that can read/write the state s with side-effects and finally produce an a. Even if it is pure, sometimes it is convenient to pretend it's not. On topic, I'd say that effectful and with effects mean the same thing, even if they are sometimes applied broadly to values wrapped in any monad/applicative, even when those do not model side effects.

– chi
Oct 28 '15 at 9:18












4 Answers
4






active

oldest

votes


















20














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 (Functors allow to modify values inside, Applicatives allow to combine effects and Monads allow effects to depend on the previous values). But in the context of Monads, 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".






share|improve this answer





















  • 2





    Could you elaborate more on the "effect" of Applicatives? After all there is a paper "Applicative Programming with effects" and I never quite understood the title (I believe I understand applicatives though)

    – Martin Drautzburg
    Oct 28 '15 at 19:54






  • 4





    @MartinDrautzburg As I wrote, the distinction between "effects" and "values" is given by the actual data type, not by the abstraction we use to manipulate it. For example, for Maybe the "effect" is always that a computation can be aborted, regardless of if we use Applicative or Monad (or other) interface. If you write f <$> a <*> b <*> c in Maybe, any of a, b or c can abort the computation with Nothing, and this is its "effect". Applicative interface allows combining effects (for Maybe it means abort on first Nothing), but doesn't allow an effect to depend on previous values.

    – Petr Pudlák
    Oct 29 '15 at 10:44



















8














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 Monads 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 S and K [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 → b is replaced by a function of type a
→ M b
. This can be read as a function that accepts an argument of type a
and returns a result of type b, with a possible additional effect captured by
M. 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 type a → b is a function of type a → [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?).






share|improve this answer

































    4














    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...







    share|improve this answer



















    • 1





      I agree to the "effect" you ascribe to the continuation monad. Other that that I am not with you. The fact that "do" notation hides the call to >>= does not make it effectful, because without that syntactic sugar the expession would be just as effectful, but not hiding >>=. The fact that it does different things depending on the type of the monad is owed to monad being a typeclass. Such things happen with all typeclasses, effectful or not.

      – Martin Drautzburg
      Oct 28 '15 at 9:51











    • OK, so obviously IO, ST and STM are only possible by doing low-level stuff that normal Haskell code can't do. Strictly speaking, all the other monads are just pure code being invisibly run. But it's still useful to think of them as being effectful computations. To some extent it's just a matter of perspective.

      – MathematicalOrchid
      Oct 28 '15 at 10:19











    • Agree with Orchid. Effectful semantics is the intended user-facing semantics for monads, and Haskell programmers in practice think in terms of effects. Implementation via pure functions is often just that, an implementation detail. It's somewhat arbitrary anyway to stop at the purely functional level of representation, when we could go further to machine code which features lots of mutable updates despite the purity of source representations.

      – András Kovács
      Oct 28 '15 at 11:02






    • 1





      A broad theme is that a computation m :: f a is pure if and only if there exists an x :: a such that m = pure x. Anything not pure in this sense has a "side effect". When f ~ Identity, every computation is pure because the only way to create something of type Identity a is by applying Identity = pure to something of type a.

      – dfeuer
      Oct 28 '15 at 14:53











    • @dfeuer, your answer looks interesting, but I did not quite understand it. @Orchid&Andreas: I understand your (good) point that "effectful" refers to a way of looking at things, rather than something you can spot in the code. But I still don't understand what way of looking at things warrants the term effectful.

      – Martin Drautzburg
      Oct 28 '15 at 16:29



















    0














    "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






    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f33386622%2fwhat-exactly-does-effectful-mean%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      20














      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 (Functors allow to modify values inside, Applicatives allow to combine effects and Monads allow effects to depend on the previous values). But in the context of Monads, 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".






      share|improve this answer





















      • 2





        Could you elaborate more on the "effect" of Applicatives? After all there is a paper "Applicative Programming with effects" and I never quite understood the title (I believe I understand applicatives though)

        – Martin Drautzburg
        Oct 28 '15 at 19:54






      • 4





        @MartinDrautzburg As I wrote, the distinction between "effects" and "values" is given by the actual data type, not by the abstraction we use to manipulate it. For example, for Maybe the "effect" is always that a computation can be aborted, regardless of if we use Applicative or Monad (or other) interface. If you write f <$> a <*> b <*> c in Maybe, any of a, b or c can abort the computation with Nothing, and this is its "effect". Applicative interface allows combining effects (for Maybe it means abort on first Nothing), but doesn't allow an effect to depend on previous values.

        – Petr Pudlák
        Oct 29 '15 at 10:44
















      20














      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 (Functors allow to modify values inside, Applicatives allow to combine effects and Monads allow effects to depend on the previous values). But in the context of Monads, 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".






      share|improve this answer





















      • 2





        Could you elaborate more on the "effect" of Applicatives? After all there is a paper "Applicative Programming with effects" and I never quite understood the title (I believe I understand applicatives though)

        – Martin Drautzburg
        Oct 28 '15 at 19:54






      • 4





        @MartinDrautzburg As I wrote, the distinction between "effects" and "values" is given by the actual data type, not by the abstraction we use to manipulate it. For example, for Maybe the "effect" is always that a computation can be aborted, regardless of if we use Applicative or Monad (or other) interface. If you write f <$> a <*> b <*> c in Maybe, any of a, b or c can abort the computation with Nothing, and this is its "effect". Applicative interface allows combining effects (for Maybe it means abort on first Nothing), but doesn't allow an effect to depend on previous values.

        – Petr Pudlák
        Oct 29 '15 at 10:44














      20












      20








      20







      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 (Functors allow to modify values inside, Applicatives allow to combine effects and Monads allow effects to depend on the previous values). But in the context of Monads, 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".






      share|improve this answer















      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 (Functors allow to modify values inside, Applicatives allow to combine effects and Monads allow effects to depend on the previous values). But in the context of Monads, 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".







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Oct 28 '15 at 18:47









      dfeuer

      33k349130




      33k349130










      answered Oct 28 '15 at 17:57









      Petr PudlákPetr Pudlák

      45.5k6114266




      45.5k6114266








      • 2





        Could you elaborate more on the "effect" of Applicatives? After all there is a paper "Applicative Programming with effects" and I never quite understood the title (I believe I understand applicatives though)

        – Martin Drautzburg
        Oct 28 '15 at 19:54






      • 4





        @MartinDrautzburg As I wrote, the distinction between "effects" and "values" is given by the actual data type, not by the abstraction we use to manipulate it. For example, for Maybe the "effect" is always that a computation can be aborted, regardless of if we use Applicative or Monad (or other) interface. If you write f <$> a <*> b <*> c in Maybe, any of a, b or c can abort the computation with Nothing, and this is its "effect". Applicative interface allows combining effects (for Maybe it means abort on first Nothing), but doesn't allow an effect to depend on previous values.

        – Petr Pudlák
        Oct 29 '15 at 10:44














      • 2





        Could you elaborate more on the "effect" of Applicatives? After all there is a paper "Applicative Programming with effects" and I never quite understood the title (I believe I understand applicatives though)

        – Martin Drautzburg
        Oct 28 '15 at 19:54






      • 4





        @MartinDrautzburg As I wrote, the distinction between "effects" and "values" is given by the actual data type, not by the abstraction we use to manipulate it. For example, for Maybe the "effect" is always that a computation can be aborted, regardless of if we use Applicative or Monad (or other) interface. If you write f <$> a <*> b <*> c in Maybe, any of a, b or c can abort the computation with Nothing, and this is its "effect". Applicative interface allows combining effects (for Maybe it means abort on first Nothing), but doesn't allow an effect to depend on previous values.

        – Petr Pudlák
        Oct 29 '15 at 10:44








      2




      2





      Could you elaborate more on the "effect" of Applicatives? After all there is a paper "Applicative Programming with effects" and I never quite understood the title (I believe I understand applicatives though)

      – Martin Drautzburg
      Oct 28 '15 at 19:54





      Could you elaborate more on the "effect" of Applicatives? After all there is a paper "Applicative Programming with effects" and I never quite understood the title (I believe I understand applicatives though)

      – Martin Drautzburg
      Oct 28 '15 at 19:54




      4




      4





      @MartinDrautzburg As I wrote, the distinction between "effects" and "values" is given by the actual data type, not by the abstraction we use to manipulate it. For example, for Maybe the "effect" is always that a computation can be aborted, regardless of if we use Applicative or Monad (or other) interface. If you write f <$> a <*> b <*> c in Maybe, any of a, b or c can abort the computation with Nothing, and this is its "effect". Applicative interface allows combining effects (for Maybe it means abort on first Nothing), but doesn't allow an effect to depend on previous values.

      – Petr Pudlák
      Oct 29 '15 at 10:44





      @MartinDrautzburg As I wrote, the distinction between "effects" and "values" is given by the actual data type, not by the abstraction we use to manipulate it. For example, for Maybe the "effect" is always that a computation can be aborted, regardless of if we use Applicative or Monad (or other) interface. If you write f <$> a <*> b <*> c in Maybe, any of a, b or c can abort the computation with Nothing, and this is its "effect". Applicative interface allows combining effects (for Maybe it means abort on first Nothing), but doesn't allow an effect to depend on previous values.

      – Petr Pudlák
      Oct 29 '15 at 10:44













      8














      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 Monads 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 S and K [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 → b is replaced by a function of type a
      → M b
      . This can be read as a function that accepts an argument of type a
      and returns a result of type b, with a possible additional effect captured by
      M. 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 type a → b is a function of type a → [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?).






      share|improve this answer






























        8














        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 Monads 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 S and K [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 → b is replaced by a function of type a
        → M b
        . This can be read as a function that accepts an argument of type a
        and returns a result of type b, with a possible additional effect captured by
        M. 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 type a → b is a function of type a → [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?).






        share|improve this answer




























          8












          8








          8







          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 Monads 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 S and K [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 → b is replaced by a function of type a
          → M b
          . This can be read as a function that accepts an argument of type a
          and returns a result of type b, with a possible additional effect captured by
          M. 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 type a → b is a function of type a → [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?).






          share|improve this answer















          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 Monads 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 S and K [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 → b is replaced by a function of type a
          → M b
          . This can be read as a function that accepts an argument of type a
          and returns a result of type b, with a possible additional effect captured by
          M. 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 type a → b is a function of type a → [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?).







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 22 '18 at 4:28

























          answered Mar 6 '18 at 13:49









          duplodeduplode

          23k44885




          23k44885























              4














              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...







              share|improve this answer



















              • 1





                I agree to the "effect" you ascribe to the continuation monad. Other that that I am not with you. The fact that "do" notation hides the call to >>= does not make it effectful, because without that syntactic sugar the expession would be just as effectful, but not hiding >>=. The fact that it does different things depending on the type of the monad is owed to monad being a typeclass. Such things happen with all typeclasses, effectful or not.

                – Martin Drautzburg
                Oct 28 '15 at 9:51











              • OK, so obviously IO, ST and STM are only possible by doing low-level stuff that normal Haskell code can't do. Strictly speaking, all the other monads are just pure code being invisibly run. But it's still useful to think of them as being effectful computations. To some extent it's just a matter of perspective.

                – MathematicalOrchid
                Oct 28 '15 at 10:19











              • Agree with Orchid. Effectful semantics is the intended user-facing semantics for monads, and Haskell programmers in practice think in terms of effects. Implementation via pure functions is often just that, an implementation detail. It's somewhat arbitrary anyway to stop at the purely functional level of representation, when we could go further to machine code which features lots of mutable updates despite the purity of source representations.

                – András Kovács
                Oct 28 '15 at 11:02






              • 1





                A broad theme is that a computation m :: f a is pure if and only if there exists an x :: a such that m = pure x. Anything not pure in this sense has a "side effect". When f ~ Identity, every computation is pure because the only way to create something of type Identity a is by applying Identity = pure to something of type a.

                – dfeuer
                Oct 28 '15 at 14:53











              • @dfeuer, your answer looks interesting, but I did not quite understand it. @Orchid&Andreas: I understand your (good) point that "effectful" refers to a way of looking at things, rather than something you can spot in the code. But I still don't understand what way of looking at things warrants the term effectful.

                – Martin Drautzburg
                Oct 28 '15 at 16:29
















              4














              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...







              share|improve this answer



















              • 1





                I agree to the "effect" you ascribe to the continuation monad. Other that that I am not with you. The fact that "do" notation hides the call to >>= does not make it effectful, because without that syntactic sugar the expession would be just as effectful, but not hiding >>=. The fact that it does different things depending on the type of the monad is owed to monad being a typeclass. Such things happen with all typeclasses, effectful or not.

                – Martin Drautzburg
                Oct 28 '15 at 9:51











              • OK, so obviously IO, ST and STM are only possible by doing low-level stuff that normal Haskell code can't do. Strictly speaking, all the other monads are just pure code being invisibly run. But it's still useful to think of them as being effectful computations. To some extent it's just a matter of perspective.

                – MathematicalOrchid
                Oct 28 '15 at 10:19











              • Agree with Orchid. Effectful semantics is the intended user-facing semantics for monads, and Haskell programmers in practice think in terms of effects. Implementation via pure functions is often just that, an implementation detail. It's somewhat arbitrary anyway to stop at the purely functional level of representation, when we could go further to machine code which features lots of mutable updates despite the purity of source representations.

                – András Kovács
                Oct 28 '15 at 11:02






              • 1





                A broad theme is that a computation m :: f a is pure if and only if there exists an x :: a such that m = pure x. Anything not pure in this sense has a "side effect". When f ~ Identity, every computation is pure because the only way to create something of type Identity a is by applying Identity = pure to something of type a.

                – dfeuer
                Oct 28 '15 at 14:53











              • @dfeuer, your answer looks interesting, but I did not quite understand it. @Orchid&Andreas: I understand your (good) point that "effectful" refers to a way of looking at things, rather than something you can spot in the code. But I still don't understand what way of looking at things warrants the term effectful.

                – Martin Drautzburg
                Oct 28 '15 at 16:29














              4












              4








              4







              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...







              share|improve this answer













              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...








              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Oct 28 '15 at 9:34









              MathematicalOrchidMathematicalOrchid

              40k1598187




              40k1598187








              • 1





                I agree to the "effect" you ascribe to the continuation monad. Other that that I am not with you. The fact that "do" notation hides the call to >>= does not make it effectful, because without that syntactic sugar the expession would be just as effectful, but not hiding >>=. The fact that it does different things depending on the type of the monad is owed to monad being a typeclass. Such things happen with all typeclasses, effectful or not.

                – Martin Drautzburg
                Oct 28 '15 at 9:51











              • OK, so obviously IO, ST and STM are only possible by doing low-level stuff that normal Haskell code can't do. Strictly speaking, all the other monads are just pure code being invisibly run. But it's still useful to think of them as being effectful computations. To some extent it's just a matter of perspective.

                – MathematicalOrchid
                Oct 28 '15 at 10:19











              • Agree with Orchid. Effectful semantics is the intended user-facing semantics for monads, and Haskell programmers in practice think in terms of effects. Implementation via pure functions is often just that, an implementation detail. It's somewhat arbitrary anyway to stop at the purely functional level of representation, when we could go further to machine code which features lots of mutable updates despite the purity of source representations.

                – András Kovács
                Oct 28 '15 at 11:02






              • 1





                A broad theme is that a computation m :: f a is pure if and only if there exists an x :: a such that m = pure x. Anything not pure in this sense has a "side effect". When f ~ Identity, every computation is pure because the only way to create something of type Identity a is by applying Identity = pure to something of type a.

                – dfeuer
                Oct 28 '15 at 14:53











              • @dfeuer, your answer looks interesting, but I did not quite understand it. @Orchid&Andreas: I understand your (good) point that "effectful" refers to a way of looking at things, rather than something you can spot in the code. But I still don't understand what way of looking at things warrants the term effectful.

                – Martin Drautzburg
                Oct 28 '15 at 16:29














              • 1





                I agree to the "effect" you ascribe to the continuation monad. Other that that I am not with you. The fact that "do" notation hides the call to >>= does not make it effectful, because without that syntactic sugar the expession would be just as effectful, but not hiding >>=. The fact that it does different things depending on the type of the monad is owed to monad being a typeclass. Such things happen with all typeclasses, effectful or not.

                – Martin Drautzburg
                Oct 28 '15 at 9:51











              • OK, so obviously IO, ST and STM are only possible by doing low-level stuff that normal Haskell code can't do. Strictly speaking, all the other monads are just pure code being invisibly run. But it's still useful to think of them as being effectful computations. To some extent it's just a matter of perspective.

                – MathematicalOrchid
                Oct 28 '15 at 10:19











              • Agree with Orchid. Effectful semantics is the intended user-facing semantics for monads, and Haskell programmers in practice think in terms of effects. Implementation via pure functions is often just that, an implementation detail. It's somewhat arbitrary anyway to stop at the purely functional level of representation, when we could go further to machine code which features lots of mutable updates despite the purity of source representations.

                – András Kovács
                Oct 28 '15 at 11:02






              • 1





                A broad theme is that a computation m :: f a is pure if and only if there exists an x :: a such that m = pure x. Anything not pure in this sense has a "side effect". When f ~ Identity, every computation is pure because the only way to create something of type Identity a is by applying Identity = pure to something of type a.

                – dfeuer
                Oct 28 '15 at 14:53











              • @dfeuer, your answer looks interesting, but I did not quite understand it. @Orchid&Andreas: I understand your (good) point that "effectful" refers to a way of looking at things, rather than something you can spot in the code. But I still don't understand what way of looking at things warrants the term effectful.

                – Martin Drautzburg
                Oct 28 '15 at 16:29








              1




              1





              I agree to the "effect" you ascribe to the continuation monad. Other that that I am not with you. The fact that "do" notation hides the call to >>= does not make it effectful, because without that syntactic sugar the expession would be just as effectful, but not hiding >>=. The fact that it does different things depending on the type of the monad is owed to monad being a typeclass. Such things happen with all typeclasses, effectful or not.

              – Martin Drautzburg
              Oct 28 '15 at 9:51





              I agree to the "effect" you ascribe to the continuation monad. Other that that I am not with you. The fact that "do" notation hides the call to >>= does not make it effectful, because without that syntactic sugar the expession would be just as effectful, but not hiding >>=. The fact that it does different things depending on the type of the monad is owed to monad being a typeclass. Such things happen with all typeclasses, effectful or not.

              – Martin Drautzburg
              Oct 28 '15 at 9:51













              OK, so obviously IO, ST and STM are only possible by doing low-level stuff that normal Haskell code can't do. Strictly speaking, all the other monads are just pure code being invisibly run. But it's still useful to think of them as being effectful computations. To some extent it's just a matter of perspective.

              – MathematicalOrchid
              Oct 28 '15 at 10:19





              OK, so obviously IO, ST and STM are only possible by doing low-level stuff that normal Haskell code can't do. Strictly speaking, all the other monads are just pure code being invisibly run. But it's still useful to think of them as being effectful computations. To some extent it's just a matter of perspective.

              – MathematicalOrchid
              Oct 28 '15 at 10:19













              Agree with Orchid. Effectful semantics is the intended user-facing semantics for monads, and Haskell programmers in practice think in terms of effects. Implementation via pure functions is often just that, an implementation detail. It's somewhat arbitrary anyway to stop at the purely functional level of representation, when we could go further to machine code which features lots of mutable updates despite the purity of source representations.

              – András Kovács
              Oct 28 '15 at 11:02





              Agree with Orchid. Effectful semantics is the intended user-facing semantics for monads, and Haskell programmers in practice think in terms of effects. Implementation via pure functions is often just that, an implementation detail. It's somewhat arbitrary anyway to stop at the purely functional level of representation, when we could go further to machine code which features lots of mutable updates despite the purity of source representations.

              – András Kovács
              Oct 28 '15 at 11:02




              1




              1





              A broad theme is that a computation m :: f a is pure if and only if there exists an x :: a such that m = pure x. Anything not pure in this sense has a "side effect". When f ~ Identity, every computation is pure because the only way to create something of type Identity a is by applying Identity = pure to something of type a.

              – dfeuer
              Oct 28 '15 at 14:53





              A broad theme is that a computation m :: f a is pure if and only if there exists an x :: a such that m = pure x. Anything not pure in this sense has a "side effect". When f ~ Identity, every computation is pure because the only way to create something of type Identity a is by applying Identity = pure to something of type a.

              – dfeuer
              Oct 28 '15 at 14:53













              @dfeuer, your answer looks interesting, but I did not quite understand it. @Orchid&Andreas: I understand your (good) point that "effectful" refers to a way of looking at things, rather than something you can spot in the code. But I still don't understand what way of looking at things warrants the term effectful.

              – Martin Drautzburg
              Oct 28 '15 at 16:29





              @dfeuer, your answer looks interesting, but I did not quite understand it. @Orchid&Andreas: I understand your (good) point that "effectful" refers to a way of looking at things, rather than something you can spot in the code. But I still don't understand what way of looking at things warrants the term effectful.

              – Martin Drautzburg
              Oct 28 '15 at 16:29











              0














              "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






              share|improve this answer




























                0














                "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






                share|improve this answer


























                  0












                  0








                  0







                  "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






                  share|improve this answer













                  "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







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Sep 22 '18 at 8:48









                  Philip SchwarzPhilip Schwarz

                  512




                  512






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f33386622%2fwhat-exactly-does-effectful-mean%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

                      Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

                      A Topological Invariant for $pi_3(U(n))$