1. 14

  2. 7

    Flow user here, love it. Use it everyday. I simply re-export it via my custom prelude, then import my custom prelude in all modules.

    I tried not using Flow for a while, but what I found was that, when I’m multiple levels deep into some codepath (you know when you lose track of space and time and get lost in the logic) and I need to decide what a function does, it’s much easier to read |> than $; trying to mentally parse $ takes me out of the context of the codepath and then I have to re-gain my bearings before I start writing code, and it’s worse when I have to reverse the order of the logic[1]. I think this is because of onomatopoeia: the |> function looks like it pipes some data through a function, whereas $ does not give me that impression at all. The standard >>= also looks like it pipes some data through a monad.

    [1]: Consider this:

    sequence $ func2 $ map func1 $ myData

    versus this:

    |> map func1
    |> func2
    |> sequence

    IMO the second is so much nicer to read and follow.

    1. 4

      So far the comments I’ve shown have been personal attacks

      Only 2 of the 6 comments up to the point this comment is made have anything personal in them. They seem to be “attacking” the concepts, not the person.

      1. 6

        Hi! Author here. Now that I’ve had some time to mellow, I wouldn’t call those “personal attacks”. At the time I was excited about functional pipelines (probably thanks to Elixir). No Haskell libraries provided the (|>) pipeline operator. I created Flow to fill that gap. I shared it on Reddit because I wanted to know why pipelines weren’t popular in the Haskell community. It got over 100 comments, which is huge for r/haskell. In my opinion, most of the comments were negative. They derided the library by calling it “backwards” or a “hurdle” or a “crutch” or “exactly what functional programming is trying to avoid”. I took those comments personally when I shouldn’t have.

        These days I just import Data.Function ((&)) and wince a little every time I write (&) instead of (|>). It’s definitely not as popular as ($) and (.), but it’s hard to call it non-standard when it’s in the base package.

        1. 2

          I’ve always found the “backwards” notation of & a bit odd, but as you say in your post, different notations have different uses or people who prefer them. I know haskellforall has done some stuff with & around the “make Haskell look like OOP” experiments.

          I mean, >>= is in this direction as the “default” so that’s not uncommon at all. I wonder if you could do some fun stuff with >>= and Identity

          1. 2

            I usually prefer (&) because it encourages iterative development. Start with some value, transform it, and keep doing that until you have the result you want. That’s how I usually work in GHCi. The alternative is to start at the “outside” and keep working in until you’re at the bottom. I find that way of developing to be better when I already have the type signature and I’m filling in typed holes.

            Fun fact: You can use do notation with pure computations in Haskell.

            f :: Int -> Int
            f x = do
              let y = x + 2
              let z = x * 2
              y + z
            1. 2

              Yes, you can have non-recursive let!

              test = runIdentity $ do
                   (x,s) <- return $ foo 1 []
                   (y,s) <- return $ bar x s
                   (z,s) <- return $ baz x y s
                   return (z,s)
              1. 2

                I don’t understand what the big deal is, we read from left to right not right to left. It’s just a notational convenience I really don’t understand how people could get so conservative that they can’t even handle a different direction of function composition. If you wrote right to left, I could see that being a serious inconvenience though.

          2. 4

            It’s confusing to me that the Haskell community would be resistant to the pipe operator since it’s IMO it’s been pretty successful in Elixir, Elm, F#, and OCaml. Maybe symptomatic of something unhealthy about the Haskell community in general.

            1. 1

              Yeah it’s great and haskell often forgets people like to program to do things.

              1. 2

                Avoid success at all cost taken a lil’ too far.

              2. 1

                The Haskell community is prone to err on the side of centralization to avoid fragmentation (unlike Lisps that are scattered into incompatible ecosystems, making writing anything practical much more of a chore than it should be) and has deep and ideological aversion to duct tape instead of proper fix. In this case: Flow functions are slightly more intuitive and IDE-friendly, but they do not address Haskell legacy usability problems in depth (a library is not a proper place for fixing the language), thus the community is very reluctant to use this.

                I don’t see anything unhealthy about this, it is a conscious and rational choice (that has its downsides, yes).