# How do you guys deal with monads?

**URL:** <https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908>\
**Category:** Request Feedback\
**Created:** [January 25, 2023, 8:12pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908 "2023-01-25T20:12:38Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mckahz](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mckahz](https://discourse.elm-lang.org/u/mckahz)\
**Post date:** [January 25, 2023, 8:12pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/1 "2023-01-25T20:12:38Z")

</div>

For those familiar with monads…

I understand why Elm doesn’t have an infix bind or a do notation because 1. it wouldn’t even work because Elm doesn’t support that level of polymorphism because 2. it’s a level of complexity which scares newbies off, which is very opposed to Elm’s design philosophy. With that said, any function I’m writing which has multiple points of failure gets really ugly really fast without do notation. I don’t love the idea of using `elm-do` since my code will become unreadable to other Elm users. I’ve also tried a couple other things that don’t work with `elm-fmt` very well. This is a big enough deal for me that it was the tipping point for me to stop using `elm-fmt`- though I guess this was the straw that broke the camels back. I get that long files don’t really matter but case statements test me. This is the solution I like the most, transforming this (ignore the details, just focus on formatting)-

```elm
extractTag : String -> Result Parser.Problem ( Tag, String )
extractTag str =
    Parser.run openTagParser str
        |> Result.andThen 
            (\( name, attributes, afterOpenTag ) ->
                Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
                    |> Result.map (\( inside, rest ) ->
                        ( { name = name, attributes = attributes, inside = inside }, rest )
                    )
            )

```

Into this-

```elm
extractTag : String -> Result Parser.Problem ( Tag, String )
extractTag str =
    Parser.run openTagParser str
    |> Result.andThen <| 
    \( name, attributes, afterOpenTag ) ->

    Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
    |> Result.map <| 
    \( inside, rest ) ->

    ( { name = name, attributes = attributes, inside = inside }, rest )

```

I like this solution because whenever we have `|> M.[andThen/map] <|` we’re essentially saying "bind what’s above to what’s below as if it weren’t an `M`.

What do you guys think? Do you think it makes more sense to just make more function definitions to reduce nesting? Do you just use `elm-do`? How do you go about it? Do you have any better solutions?

---

<div class="post-metadata">

**Author:** ![mckahz](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mckahz](https://discourse.elm-lang.org/u/mckahz)\
**Post date:** [January 25, 2023, 8:15pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/2 "2023-01-25T20:15:50Z")

</div>

For the curious among you, this is a function I’m using in an HTML parsing library I’m writing.

---

<div class="post-metadata">

**Author:** ![wolfadex](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/wolfadex/32/2461_2.png) [@wolfadex](https://discourse.elm-lang.org/u/wolfadex)\
**Post date:** [January 25, 2023, 9:08pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/3 "2023-01-25T21:08:55Z")

</div>

Want to start out with this is just my opinion and I always prefer `elm-format` because I’d rather spend my time writing features than debating formatting. However given that you’ve specifically asked about formatting I’ll give my opinion if I wanted the choice.

* * *

I stopped reading at `|> Result.andThen <|` because I don’t know the order of operations and I wouldn’t want to have to memorize it. Either all `|>` or all `<|` but I really dislike mixing them.

When I saw

```elm
extractTag : String -> Result Parser.Problem ( Tag, String )
extractTag str =
    Parser.run openTagParser str
        |> Result.andThen 
            (\( name, attributes, afterOpenTag ) ->
                Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
                    |> Result.map (\( inside, rest ) ->
                        ( { name = name, attributes = attributes, inside = inside }, rest )
                    )
            )

```

my first thought was to do

```elm
extractTag : String -> Result Parser.Problem ( Tag, String )
extractTag str =
    Parser.run openTagParser str
        |> Result.andThen parseExtractTagResult

parseExtractTagResult : ( String, ???, String ) -> Result Parser.Problem ( Tag, String )
parseExtractTagResult ( name, attributes, afterOpenTag ) =
    Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
        |> Result.map
            (\( inside, rest ) ->
                ( { name = name, attributes = attributes, inside = inside }, rest )
            )

```

Naming aside, as I don’t know the full context here, this to me is already significantly easier to read and maintain because I’m only looking at small chunks of parsers at a time. It also still fits with `elm-format`, and there’s 0 thinking about what the order of operations is.

---

<div class="post-metadata">

**Author:** ![lydell](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lydell/32/178_2.png) [@lydell](https://discourse.elm-lang.org/u/lydell)\
**Post date:** [January 25, 2023, 9:25pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/4 "2023-01-25T21:25:19Z")

</div>

> [@wolfadex](#):
>
> I stopped reading at `|> Result.andThen <|` because I don’t know the order of operations and I wouldn’t want to have to memorize it. Either all `|>` or all `<|` but I really dislike mixing them.

The compiler does not like it either 🙂

```auto
-- INFIX PROBLEM ----------------------------------------------------------------

You cannot mix (|>) and (<|) without parentheses.

62|> Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
63|> |> Result.map <| 
64|> \( inside, rest ) ->
65|>
66|> ( { name = name, attributes = attributes, inside = inside }, rest )

I do not know how to group these expressions. Add parentheses for me!

```

* * *

In my opinion, the first code snippet posted is fine as-is.

I break it up into more functions when it gets even more nested or too long.

---

<div class="post-metadata">

**Author:** ![benjamin-thomas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/benjamin-thomas/32/3869_2.png) [@benjamin-thomas](https://discourse.elm-lang.org/u/benjamin-thomas)\
**Post date:** [January 25, 2023, 11:07pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/5 "2023-01-25T23:07:43Z")

</div>

I hesitate to post because I may be off the marks, I’m still learning this stuff, but here goes.

At the moment, in my mind, `andThen` = `bind` = “monadic pattern”.

I was working on a little exercise lately, where I wanted to compute a list of results, to return either a failure, or a list of `a`s (the computation should stop on first failure)

```auto
compute : List (Result error a) -> Result error (List a)

```

My first iteration looked like this:

```auto
compute = List.foldr (\ra rb -> ra |> Result.andThen (\x -> rb |> Result.map (\y -> x :: y))) (Ok [])

```

My second iteration looked like this:

```auto
thenApply f ra rb =
    ra |> Result.andThen (\x -> rb |> Result.map (\y -> f x y))

compute = List.foldr (thenApply (::)) (Ok [])

```

I then realized I had actually re-implemented map2!

So my third iteration was just:

```auto
compute = List.foldr (Result.map2 (::)) (Ok [])

```

So to sum up, I registered in my brain that `andThen` followed by `map` = `map2`. Not totally sure if it’s applicable to your situation though.

What I found interesting is that I first worked on this programming problem in another language, that provided less constraints and other code organization techniques. And implementation n°1 seemed fine.

So to sum up, I don’t have any definitive conclusions 🙂

If you feel discomfort regarding ugly code, maybe you missed some patterns, some other ways to organize your code better (in Elm)

---

<div class="post-metadata">

**Author:** ![mckahz](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mckahz](https://discourse.elm-lang.org/u/mckahz)\
**Post date:** [January 26, 2023, 4:49pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/6 "2023-01-26T16:49:49Z")

</div>

As lydell pointed out, apparently it doesn’t even compile! My IDE wasn’t type checking apparently because I wasn’t getting any errors. I don’t see why it doesn’t compile though, since `<|` and `|>` should just be right associative with the same precedence, and I don’t think that’s too much mental overhead.

The thing is, if nothing here returns a result then the code is short, understandable, and easy to write. As soon as we introduce errors (which you should absolutely do) it becomes long, confusing, and formats horribly. I think `elm-format` generally is good but has a lot of bad rules, and this is one of them.

I think it would make sense for elm to implement a polymorphic bind operator since it’s pretty easy to describe- just replace `>>=` with `|> Result.andThen` if you’re confused. `|>=` might make more sense because it takes a value rather than composing functions, but I digress.

> [@wolfadex](#):
>
> ```auto
> extractTag : String -> Result Parser.Problem ( Tag, String )
> extractTag str =
> Parser.run openTagParser str
> |> Result.andThen parseExtractTagResult
> 
> parseExtractTagResult : ( String, ???, String ) -> Result Parser.Problem ( Tag, String )
> parseExtractTagResult ( name, attributes, afterOpenTag ) =
> Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
> |> Result.map
> (\( inside, rest ) ->
> ( { name = name, attributes = attributes, inside = inside }, rest )
> )
> 
> ```

One of the greatest things about FP is the ability not to name nearly as much stuff and still have perfectly legible code, so it would suck if this was the only sensible way to do it in Elm.

---

<div class="post-metadata">

**Author:** ![mckahz](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mckahz](https://discourse.elm-lang.org/u/mckahz)\
**Post date:** [January 26, 2023, 4:51pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/7 "2023-01-26T16:51:31Z")

</div>

Thanks for checking that my code doesn’t work, I wrote this before I went to bed so I hadn’t run it yet. Shame, I was hoping this was a viable solution.

Is the first code snippet not too long/nested? I wrote the code and even I can barely understand it.

---

<div class="post-metadata">

**Author:** ![mckahz](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mckahz](https://discourse.elm-lang.org/u/mckahz)\
**Post date:** [January 26, 2023, 5:14pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/8 "2023-01-26T17:14:21Z")

</div>

> [@benjamin-thomas](#):
>
> At the moment, in my mind, `andThen` = `bind` = “monadic pattern”.

Yup, the only difference is bind is usually infix, so the following 2 are the same

```elm
value |> Result.andThen (\x -> ...)

```

```elm
value >>= (\x -> ...)

```

So if we had a bind operator in Elm (which I think is within the limit of complexity of Elm- I don’t think it’s any harder to understand than `andThen`) we could clean up my example like so- first I’m gonna change the `map` to and `andThen` (you’ll see why in a second)

```elm
extractTag : String -> Result Parser.Problem ( Tag, String )
extractTag str =
    Parser.run openTagParser str
        |> Result.andThen 
            (\( name, attributes, afterOpenTag ) ->
                Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
                    |> Result.andThen (\( inside, rest ) ->
                        Ok ( { name = name, attributes = attributes, inside = inside }, rest )
                    )
            )

```

so that _could_ become

```elm
extractTag : String -> Result Parser.Problem ( Tag, String )
extractTag str =
    Parser.run openTagParser str
        >>= (\( name, attributes, afterOpenTag ) ->
            Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
                >>= (\( inside, rest ) ->
                        Ok ( { name = name, attributes = attributes, inside = inside }, rest )
                    )
            )

```

And since the lambdas are the last thing within the brackets they’re in, we can remove them,

```elm
extractTag : String -> Result Parser.Problem ( Tag, String )
extractTag str =
    Parser.run openTagParser str
        >>= \( name, attributes, afterOpenTag ) ->
            Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
                >>= \( inside, rest ) ->
                        Ok ( { name = name, attributes = attributes, inside = inside }, rest )

```

and if we change the formatting a bit, we get

```elm
extractTag : String -> Result Parser.Problem ( Tag, String )
extractTag str =
    Parser.run ... ... >>= \( name, attributes, afterOpenTag ) ->
    Parser.run (...) (...) >>= \( inside, rest ) ->
    Ok ( { name = name, attributes = attributes, inside = inside }, rest )

```

now the first 2 lines are kinda saying "evaluate `Parser.run (...) (...)` and then let `( name, attributes, afterOpenTag ) / ( inside, rest )` be the value only if it’s a success. But it would be nice if it looked something like `valueIfOk = functionThatReturnsResult args`, which is what the do notation in Haskell does-

```elm
extractTag : String -> Result Parser.Problem ( Tag, String )
extractTag str = do
    ( name, attributes, afterOpenTag ) <- Parser.run openTagParser str
    ( inside, rest ) <- Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
    Ok ( { name = name, attributes = attributes, inside = inside }, rest )

```

But what we have no looks surprisingly imperative, and in light of that, Haskell would let us write `return` instead of `Ok`

```elm
extractTag : String -> Result Parser.Problem ( Tag, String )
extractTag str = do
    ( name, attributes, afterOpenTag ) <- Parser.run openTagParser str
    ( inside, rest ) <- Parser.run (insideStringToParser name) ("<" ++ name ++ ">" ++ afterOpenTag)
    return ( { name = name, attributes = attributes, inside = inside }, rest )

```

Now there’s a lot of hidden complexity here, but you would have a hard time arguing that this is more difficult to comprehend than the code we started with. Even the example with `>>=` and without `do` notation is way easier to write / understand if you learn what `>>=` does (which as I said in a previous reply, you can just replace it with `|> Result.andThen` and it will mean the same thing.

> [@benjamin-thomas](#):
>
> So to sum up, I registered in my brain that `andThen` followed by `map` = `map2`. Not totally sure if it’s applicable to your situation though.

They’re not equal, since you can’t use the value from the value fed into andThen in map, which is what I needed.

> [@benjamin-thomas](#):
>
> If you feel discomfort regarding ugly code, maybe you missed some patterns, some other ways to organize your code better (in Elm)

Well that’s why I’m here! Though this is the most famous pattern in FP. Because it makes functions where there’s a bunch of [Result / Maybe / Parser / List]s way easier to read and type. Well, that’s not the actual reason. The actual reason Monads are as big as they are is because they allow things like IO to be segmented nicely from the rest of the code- but it’s the bind that makes it nice to work with! That’s why Haskell’s logo is the bind operator! Because it makes Monads (Result / Maybe / Parser / List / IO) much nicer to deal with. It’s a really powerful and ubiquitous pattern, which is why I think Elm should have better support for it, even at the cost of a tiny amount of complexity.

---

<div class="post-metadata">

**Author:** ![solificati](https://avatars.discourse-cdn.com/v4/letter/s/2bfe46/32.png) [@solificati](https://discourse.elm-lang.org/u/solificati)\
**Post date:** [January 26, 2023, 5:32pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/9 "2023-01-26T17:32:33Z")

</div>

> [@benjamin-thomas](#):
>
> At the moment, in my mind, `andThen` = `bind` = “monadic pattern”.

In some limited way, yes. But if we don’t have polymorphism over monad type it’s very hard to talk about “nomadic” anything. It’s like calling array iterable, but that array can have only one element.

---

<div class="post-metadata">

**Author:** ![wolfadex](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/wolfadex/32/2461_2.png) [@wolfadex](https://discourse.elm-lang.org/u/wolfadex)\
**Post date:** [January 26, 2023, 5:47pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/10 "2023-01-26T17:47:17Z")

</div>

> `<|` and `|>` should just be right associative with the same precedence, and I don’t think that’s too much mental overhead.

And yet I said that I, upon first looking at it, was unable to determine what the order of operations should be. I read and write Elm about 60+ hrs a week (likely more than that) and it still wasn’t readily apparent to me what should happen there.

> One of the greatest things about FP is the ability not to name nearly as much stuff and still have perfectly legible code, so it would suck if this was the only sensible way to do it in Elm.

I’m completely onboard for not naming things. I even write my own toy concatenative languages because I find joy in having no names at all, including naming variables! However when it comes to Elm I don’t see any of that being a target. I’d say [news/the-syntax-cliff](https://elm-lang.org/news/the-syntax-cliff) is a great example of what Elm is targeting. Elm doesn’t care about FP or whether things are named or not, what it cares about is the joy of everyone being included and everyone being able to create. That you are able to understand the existing syntax and other aren’t says to me that if any change is to be made, it should be made in a way that makes things easier not harder.

---

<div class="post-metadata">

**Author:** ![mckahz](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mckahz](https://discourse.elm-lang.org/u/mckahz)\
**Post date:** [January 26, 2023, 6:06pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/11 "2023-01-26T18:06:27Z")

</div>

> [@wolfadex](#):
>
> I read and write Elm about 60+ hrs a week (likely more than that) and it still wasn’t readily apparent to me what should happen there.

I mean it would be odd if they had different precedent, since they’re symmetrical, and it would be weird if they were left associative since operators never are. I would agree that this would be too much technical jargon for a new comer but you have to understand this to use the most basic operator in Elm- `(::)`.

> [@wolfadex](#):
>
> I even write my own toy concatenative languages because I find joy in having no names at all, including naming variables!

I would love to try a concatenative language! I still have a few languages I’d like to try before that though (APL or J or BQN → Racket or Clojure → Furthark). Other paradigms interest me a lot! (Kinda how I ended up here haha)

> [@wolfadex](#):
>
> what it cares about is the joy of everyone being included and everyone being able to create. That you are able to understand the existing syntax and other aren’t says to me that if any change is to be made, it should be made in a way that makes things easier not harder.

Sure but Elm introduces some complex things because they’re too damn useful. You can write polymorphic functions in Elm, and I would say that’s a harder (though probably more common) concept than Monads in FP. I think it’s more about the tradeoff between complexity and usefulness. Evan clearly thinks bind / related ideas are too complex for most people and that’s fine, but Monads are everywhere in FP and I would _really_ like better support for them as much as I know / sympathize with the fact that it’s not gonna happen.

I should probably make my own teaching language as a test to see if I can teach Monads as easily as I think I can. Posts teaching Monads in Elm are actually a lot better than in Haskell, so I think the complexity is more about community than language design.

---

<div class="post-metadata">

**Author:** ![benjamin-thomas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/benjamin-thomas/32/3869_2.png) [@benjamin-thomas](https://discourse.elm-lang.org/u/benjamin-thomas)\
**Post date:** [January 26, 2023, 6:14pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/12 "2023-01-26T18:14:35Z")

</div>

I’m with you, I’ve dabbled with a bit of Haskell and I do find that pattern beautiful, although my understanding is only superficial at the moment.

But if I understand things correctly, Elm restricts the programmer by design because constraints can have positive effects on code organization. And regarding the other complaint which is too much boilerplate due to not enough polymorphism, the answer is codegen. I have much to grow yet to feel constrained by the language but I suppose if that’s the case maybe Purescript could be a better fit?

I could maybe suggest you have a look at this well known package for inspiration: [Json.Decode.Pipeline - elm-json-decode-pipeline 1.0.1](https://package.elm-lang.org/packages/NoRedInk/elm-json-decode-pipeline/latest/Json.Decode.Pipeline)

It handles differently, the use case demoed by elm-do. I haven’t studied the package myself though (only consumed it) so forgive me if I’m off-topic.

---

<div class="post-metadata">

**Author:** ![benjamin-thomas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/benjamin-thomas/32/3869_2.png) [@benjamin-thomas](https://discourse.elm-lang.org/u/benjamin-thomas)\
**Post date:** [January 26, 2023, 6:16pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/13 "2023-01-26T18:16:54Z")

</div>

Yeah that’s where I’m at. I haven’t grokked the full picture yet, which is why I used this loose terminology 🙂

---

<div class="post-metadata">

**Author:** ![wolfadex](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/wolfadex/32/2461_2.png) [@wolfadex](https://discourse.elm-lang.org/u/wolfadex)\
**Post date:** [January 26, 2023, 6:28pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/14 "2023-01-26T18:28:20Z")

</div>

> I would agree that this would be too much technical jargon for a new comer but you have to understand this to use the most basic operator in Elm- `(::)`.

This literally tripped up a teammate of mine roughly yesterday and I had to explain it to him just 10 min ago because they didn’t understand.

From what I’ve heard, the 2 hardest things to teach in Elm are JSON encoding/decoding and currying. Not sure what it is after that, but I’ve definitely seen `Maybe` itself trip a fair amount of devs up, especially if they come from languages that have `null`, they expect it to be roughly the same when it isn’t.

* * *

If you want to understand better what would help with learning/teaching and language, I’d look at [https://hedycode.com/](https://hedycode.com/) and what McMaster University has put out about code and learning. McMaster uses Elm and Hedy is based on gradually learning Python (essentially), but very much focused on the student & teacher and how they help each other.

* * *

Somewhat related, not sure if you’ve listened to [Elm at a Billion Dollar Company with Aaron White](https://elm-radio.com/episode/elm-at-a-billion-dollar-company) but I, for the most part, agree with Aaron (I also work for him now, but felt similarly before hand). I’m definitely biased towards wanting a language that’s easy to maintain, easy to refactor, and easy to onboard onto. Elm really hits all of those far better than any other language I’ve used and I’d very much like it to stay that way. I don’t care about whether the types are fancy or not. I don’t care about whether there are `{}` and `;` for scope. Basically Elm hits a really nice sweet spot for large apps that are developed by many people over many years, and I’d love for it to remain in that sweet spot.

But this is all getting slightly off topic as well.

---

<div class="post-metadata">

**Author:** ![mckahz](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mckahz](https://discourse.elm-lang.org/u/mckahz)\
**Post date:** [January 26, 2023, 6:29pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/15 "2023-01-26T18:29:43Z")

</div>

> [@benjamin-thomas](#):
>
> I’m with you, I dabbled with a bit of Haskell and I do find that pattern beautiful, although my understanding is only superficial at the moment.

I’d love feedback as to whether my command was a good explanation! Although I’m torn between that and just saying the following are equal

```elm
x = do
    a <- someMaybeValue
    b <- someOtherMaybeValue
    return a+b

```

```elm
x =
    let a = someMaybeValue
        b = someOtherMaybeValue
    in a+b

```

Except in the first example we treat `a` and `b` like they were just numbers rather than Maybe numbers, and if either of them Nothing then `x` is nothing.

I’m not sure I love this explanation but it’s a lot easier to see the utility of it, so it might be a good explanation to proceed the first.

> [@benjamin-thomas](#):
>
> But if I understand things correctly, Elm restricts the programmer by design because constraints can have positive effects on code organization.

That’s the reason as to why it only has pure functions (and some other design choices), but the reason it doesn’t have do notation is because it’s too complex for beginners and Elm highly values accessibility. `do` notation and bind exist for the express purpose of having nicer code organization, and it would certainly help Elm’s readability, though at the expense of beginner comprehension

> [@benjamin-thomas](#):
>
> I could maybe suggest you have a look at this well known package for inspiration: [Json.Decode.Pipeline - elm-json-decode-pipeline 1.0.1](https://package.elm-lang.org/packages/NoRedInk/elm-json-decode-pipeline/latest/Json.Decode.Pipeline)

The problem I’m having is more about community/language design than what libraries I have access to. You can’t compose functions like this without some nesting unless you have bind and/or `do`.

> [@benjamin-thomas](#):
>
> It handles differently, the use case demoed by elm-do. I haven’t studied the package myself though (only consumed it) so forgive me if I’m off-topic.

Not at all! I love teaching others what I can!

.

---

<div class="post-metadata">

**Author:** ![mckahz](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mckahz](https://discourse.elm-lang.org/u/mckahz)\
**Post date:** [January 26, 2023, 6:37pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/16 "2023-01-26T18:37:27Z")

</div>

> [@wolfadex](#):
>
> From what I’ve heard, the 2 hardest things to teach in Elm are JSON encoding/decoding […]

Oh that’s common? I was having a hard time of that just recently! Elm has _really_ well designed libraries though which makes it nice and approachable.

> [@wolfadex](#):
>
> McMaster uses Elm and Hedy is based on gradually learning Python (essentially), but very much focused on the student & teacher and how they help each other.

I’ve heard of Hedy! And I have to say, it’s a really cool idea!

> [@wolfadex](#):
>
> I’m definitely biased towards wanting a language that’s easy to maintain, easy to refactor, and easy to onboard onto.

I suppose it depends on what you’re working on. I think for front end web development, Elm’s level of complexity certainly hits a sweat spot. I’m using it for something which it’s really not meant for now (parsing HTML strings) and there’s a lot of difficulties associated with but dang it, it’s just too nice of a language that it’s worth it. But if you’re working on something more technical which demands higher expertise from the programmer, then perhaps that’s the place to use a language like Elm with type classes, monad support, and a few other (somewhat simple, somewhat complex) features.

> [@wolfadex](#):
>
> But this is all getting slightly off topic as well.

I suppose it is! Thanks for the discussion!

---

<div class="post-metadata">

**Author:** ![dta](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dta/32/1917_2.png) [@dta](https://discourse.elm-lang.org/u/dta)\
**Post date:** [January 26, 2023, 6:49pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/17 "2023-01-26T18:49:09Z")

</div>

> [@mckahz](#):
>
> `<|` and `|>` should just be right associative with the same precedence

`<|` and `|>` do have the same precedence, but `<|` is right associative and `|>` is left associative.

[source](https://github.com/elm/core/blob/master/src/Basics.elm#L71-L72)

---

<div class="post-metadata">

**Author:** ![mckahz](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mckahz](https://discourse.elm-lang.org/u/mckahz)\
**Post date:** [January 26, 2023, 6:53pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/18 "2023-01-26T18:53:05Z")

</div>

Oh dip. That makes sense!

---

<div class="post-metadata">

**Author:** ![benjamin-thomas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/benjamin-thomas/32/3869_2.png) [@benjamin-thomas](https://discourse.elm-lang.org/u/benjamin-thomas)\
**Post date:** [January 26, 2023, 8:16pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/19 "2023-01-26T20:16:55Z")

</div>

> [@mckahz](#):
>
> I’d love feedback as to whether my command was a good explanation!

I think you meant “comment” not “command” right?

I don’t follow you entirely, mainly because I’m out of my comfort zone 🙂

But I do get your annoyances with the formater. Although I haven’t felt any strong discomfort with elm-format myself, I have been quite annoyed with OCaml’s, to the point where I thought about dropping it. But then, I realized that it’s a tool that can also gently guide you towards a particular (opinionated) style so I kept with it (fortunately, I could still tweak it a fair bit via its config file).

So, forgetting about elm-format, nothing stops you from formatting your code like this no?

It seems to me that we’re almost there (minus the extra parentheses). You don’t **absolutely have to** have `>>=` to make the code readable.

```auto
add ma mb =
    ma |> Maybe.andThen (\a -> 
    mb |> Maybe.andThen (\b -> 
    Just (a + b)))

```

I realized this when exploring this problem space in… Java 😅

```java
  private static Optional<Integer> add(Optional<Integer> x, Optional<Integer> y) {
        // @formatter:off
        return x.flatMap(xx ->
               y.flatMap(yy ->
               Optional.of(xx + yy)));
        // @formatter:on
    }

```

Although, yeah, this style is so far off the usual and common one that I wouldn’t do that for every day work, fighting the tooling defaults, etc. would be a pain.

---

<div class="post-metadata">

**Author:** ![mckahz](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mckahz](https://discourse.elm-lang.org/u/mckahz)\
**Post date:** [January 26, 2023, 8:42pm UTC](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908/20 "2023-01-26T20:42:23Z")

</div>

Yeah that was one of the solutions I found. I suppose it’s probably the best solution which doesn’t format nicely under `elm-fmt`. I’m a bit torn between this and just letting Elm format it and using functions but I’m thinking the latter since consistently formatted code makes a big difference.

[Next page](https://discourse.elm-lang.org/t/how-do-you-guys-deal-with-monads/8908.md?page=2)
