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)-
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-
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?