Skip to content

Instantly share code, notes, and snippets.

@knewter
Last active October 7, 2016 12:32
Show Gist options
  • Save knewter/1df87c9ae1cc67859ba6f411af90b7a7 to your computer and use it in GitHub Desktop.
Save knewter/1df87c9ae1cc67859ba6f411af90b7a7 to your computer and use it in GitHub Desktop.

Monads, Haskell, and Elm: A Socratic Dialogue

Earlier today on the elm-lang slack I witnessed a discussion about Monads that I found amazing. It was a quasi-Socratic-Dialogue style exposition of what Monads are all about, how you get them in Elm, and why those Haskell kids like them so much. The discussion took place between @hoelzro and @opsb. Behold:

@opsb: As someone that has never done much functional programming I'm curious where Monads are used in Elm (as I'd have trouble describing what they are). Am I right in thinking that anything with an andThen function is a Monad?

hoelzro: @opsb andThen can be seen as Haskell's >>=, imo

opsb: My experience is mostly OO with a sprinkling of Elixir so >>= doesn't mean anything to me (yet - I have started working through Haskell Programming)

hoelzro: oh, my bad

>>= is the function used in Haskell to pass a value in one instance of a monad to a function and generate a new instance of that monad

opsb: ok, that makes sense from where I've seen andThen used

hoelzro: iirc, though, >>= takes a (a -> m b) function, but andThen takes (a -> b)

so it's not quite the same

opsb: so with >>= you have to return a wrapped result?

enetsee: @opsb : a monad is kind of like an OOP interface, it has two ‘methods’ one of which is return and the other is bind. Elm’s andThen is bind. The equivalent of return depends on the data type - for List it has type a -> List a implemented with singleton x = [x] and for Maybe it has type a -> Maybe a implementation just x = Just x (edited)

opsb: So return "lifts" a value into a Monad?

enetsee: exactly

opsb: awesome, it's making sense

re: (a -> m b)

what's the m here?

enetsee: @opsb replace m with whatever data type you are working with, e.g. List , Maybe, Result...

opsb: right

enetsee: Other languages allow you to abstract this pattern (which is generally the source of confusion) but Elm makes you implement it explicitly for each data type

opsb:

andThen : Maybe a -> (a -> Maybe b) -> Maybe b

ah, I see, right, my understanding was the inverse. Makes sense now

hoelzro: huh, I guess andThen is (a -> m b)

opsb: yeah

enetsee: @hoelzro no - andThen is m a -> (a -> m b) -> m b for some type m

hoelzro: sorry, I meant the function provided to andThen I was correcting myself here. iirc, though, >>= takes a (a -> m b) function, but andThen takes (a -> b)

opsb: So that seems to be the same as bind in haskell?

enetsee: it is exactly bind

opsb: But in haskell you wouldn't need to write the andThen, you just use >>= and it magically works? (edited)

hoelzro: you don't even need to do that

you can

but Haskell's do notation wires everything up for you

opsb: ha

I keep hearing that being referenced

enetsee: @opsb, haskell has these things called type classes (which are again, like interfaces). To use >>= you have to declare an instance of Monad for your data type

hoelzro: so something like this:

greet = do
  name <- prompt "What's your name?"
  putStrLn $ "Hello, " ++ name

is just sugar for this:

(prompt "What's your name?") >>= (\name -> putStrLn $ "Hello, " ++  name)

enetsee: The difference with haskell is that you can then write a function once for all data types that declare that interface

enetsee: yep

opsb: seems very similar to piping

hoelzro: well, the cool thing about >>= versus piping is that if you make your own monad, you dictate exactly how >>= works

opsb: right

hoelzro: so you could (in theory) write a monad that imposes an implicit one second delay in between statements

that's why some people refer to monads as "programmable semicolons"

opsb: could you potentially pass multiple params where \name is?

hoelzro: you cannot

since the signature is m a -> (a -> m b) -> m b

opsb: gotcha

hoelzro: you could, however, return a tuple

opsb: so do is essentially a monadic pipeline?

or is ordering not important?

enetsee: @opsb you’re getting this very quickly :)

@opsb ordering is important

opsb: right, I was seeing the similarity to let (but they're obviously not that similar)

enetsee: @opsb if you rewrite it as a series of binds and functions taking monadic values you will see that you can’t carry on in the pipeline until the previous value is evaluated

opsb: This is one of the things I'm finding very attractive about functional languages, they do things I've wanted to do in the past :)

yep, that's clear now

ok, well that went well :)

learned a lot, thank you very much!

Anyway, I just wanted to share it because it was...just so nice :) I especially liked how foodstuff didn't have to enter the equation, and instead its typical stage-entry was replaced by two adult humans conversing.

Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment