
Monoids, Functors, Applicatives, and Monads: Main Ideas - abishekk92
http://monadmadness.wordpress.com/2015/01/02/monoids-functors-applicatives-and-monads-10-main-ideas/
======
DanWaterworth
I've had an idea for a monad tutorial that I think might be quite instructive,
but haven't had the motivation yet to write.

In essence, the idea is that you are led through the process of implementing:
early exit, nondeterminism, threaded state and coroutines using call/cc in
scheme. Then monads are introduced as a way of typing those patterns.

~~~
klibertp
I think most monad tutorials would be quite ok if they didn't use words like
"monad", "bind", "return" and so on. It's just stupid to insist on using names
which mean nothing or when they mean something (return) it's actually opposite
of what they're supposed to do. And no, there are no upsides to this: you
math-inclined people may think so because you were trained to think that way,
but it's simply not true.

I suspected this for a long time, but recently I saw a talk from Gilad Bracha
- [http://www.infoq.com/presentations/functional-pros-
cons](http://www.infoq.com/presentations/functional-pros-cons) \- which
convinced me that I was right. Scroll to ~22 minutes into the talk for
relevant section.

Ok, I finally said it. I feel better now, thanks ;)

~~~
dragonwriter
None of those names "mean nothing"; they all have very specific meanings. Its
true that in the case of return, the meaning in the context of Haskell monads
is somewhat special, but since its part of the actual syntax of Haskell do-
notation, its particularly important to address it in Haskell-oriented monad
tutorials, whether or not it was the best choice from a syntax design
perspective.

~~~
chriswarbo
You may already be aware of this, but for those who aren't: `return` isn't
actually part of do-notation syntax, it's a function name. It's true that do-
notation must result in a monadic value, but that's just because of the type.
`return` _can_ be used to construct that monadic value, but there are many
other ways to do so:

    
    
        func1 :: Maybe Int
        func1 = do x <- foo
                   y <- bar
                   return (x + y)  -- Using return
    
        func2 :: Maybe Int
        func2 = do x <- foo
                   y <- bar
                   Just (x + y)  -- Building a monadic value explicitly
    
        func3 :: Maybe Int
        func3 = do x <- foo
                   y <- bar
                   plusJust x y  -- Using some other function
    
        plusJust :: Int -> Int -> Maybe Int
        plusJust x y = Just (x + y)
    

Also, since `return` is a function, we can use it outside do-notation:

    
    
        wrapAndApply :: a -> (a -> b) -> [b]
        wrapAndApply x f = fmap f (return x)
    

What makes `return` "special" is that it's a method of the `Monad` typeclass.
In other words, the name `return` is overloaded to work with any instance of
`Monad` (`IO`, `Maybe`, `List`, etc.), depending on the type that's required
of it.

Loads of other functions are overloaded like this, eg. `+` has implementations
for `Int`, `Float`, etc. so it's not monad-specific.

The part which _is_ monad-specific is that Haskell's do-notation is hard-coded
to the built-in Monad typeclass. We're completely free to make our own monad
implementation, separate to Haskell's built-in one, but we won't be able to
use do-notation with them unless we implement the built-in `Monad` typeclass
_as well_. That could be as simple as mapping one name to the other:

    
    
        instance MyMonad a => Monad a
            return = myReturn
            (>>=)  = myBind

~~~
dllthomas
_" The part which is monad-specific is that Haskell's do-notation is hard-
coded to the built-in Monad typeclass."_

That's not quite true, at least in GHC. It's hard-coded to use (>>=) and fail,
but the only thing that prevents you from defining your own is the name
collision. With -XNoImplicitPrelude, you can (and they can even be locally
scoped - I did some cute things with this once that I'd never want to see in
production code...).

------
antoaravinth
Im not getting the idea of monads here. From my understanding monads does
series of transformation( composition, unit , lift ) of a function to do its
task. So does monad is similar to Adapter pattern in java? which does make two
classes work even though they aren't meant to work.

Because it does transform the class/ interface to work with other class,
right?

Am I missing anything here?

~~~
efnx
I like to think of a Monad in terms of the Monad laws, it makes it much less
abstract.
[https://www.haskell.org/haskellwiki/Monad_laws](https://www.haskell.org/haskellwiki/Monad_laws)

Different monads can have drastically different implementations but they
should all obey those laws.

~~~
AnimalMuppet
And _anything_ that obeys those laws is a monad (if I understand correctly).

[Edit: And if the implementing pieces are named correctly.]

~~~
dllthomas
I think "fmap f m = (m >>= f >>> return)" also needs to obey the functor laws.
I can quickly show that "fmap id = id" follows from the monad laws, but I
don't know whether "fmap (p . q) = (fmap p) . (fmap q)" does.

~~~
dllthomas
Ah, it does seem to follow:

    
    
        M1: return a >>= f  = f a
        M2: m >>= return    = m
        M3: (m >>= f) >>= g = m >>= (\ x -> f x >>= g)
    
        (fmap f . fmap g) m = (fmap f . fmap g) m
    
        by defn of (.)      = fmap f (fmap g m)
        by defn of fmap     = fmap f (m >>= return . g)
        by defn of fmap     = (m >>= return . g) >>= return . f
        by M3               = m >>= (\ x -> (return . g) x >>= return . f)
        by defn of (.)      = m >>= (\ x -> return (g x) >>= return . f)
        by M1               = m >>= (\ x -> (return . f) (g x))
        by defn of (.)      = m >>= (\ x -> return (f (g x)))
        by defn of (.)      = m >>= (\ x -> (return . (f . g)) x)
        eta reduction       = m >>= return . (f . g)
        by defn of fmap     = fmap (f . g) m
    
        (fmap f . fmap g) m = fmap (f . g) m

------
AnimalMuppet
Monads, applicatives, functors, and monoids are different algebras. OK. That's
really helpful, actually. (At least, I suspect it's going to be really helpful
after I've thought about it for a few days.)

But monads are the way to do sequencing? Only if you insist on putting
yourself in a functional straight-jacket that's so tight that you cannot
escape. Then, yes, you do sequencing via monads because you don't have any
other way to do it. But if you're a pragmatist rather than an ideologue, it
seems more reasonable to just do sequence _by doing things in sequence_ ,
rather than forcing yourself to do unnatural contortions.

~~~
dllthomas
_" Monads, applicatives, functors, and monoids are different algebras. OK.
That's really helpful, actually. (At least, I suspect it's going to be really
helpful after I've thought about it for a few days.)"_

I think it's not quite accurate. They're all algebraic structures, but an
"algebra" is a more specific thing and I don't _think_ they are algebras
specifically (except maybe monoid?).

[http://en.wikipedia.org/wiki/Algebraic_structure](http://en.wikipedia.org/wiki/Algebraic_structure)
[http://en.wikipedia.org/wiki/Algebra_%28ring_theory%29](http://en.wikipedia.org/wiki/Algebra_%28ring_theory%29)

 _" But monads are the way to do sequencing? Only if you insist on putting
yourself in a functional straight-jacket that's so tight that you cannot
escape."_

"Chaining actions with bind is the only way to combine actions" in Haskell is
more strongly motivated by keeping things sane in the face of _non-strict_
semantics than by a "functional straight-jacket". In fact, it wasn't the way
Haskell initially did IO.

 _" Then, yes, you do sequencing via monads because you don't have any other
way to do it. But if you're a pragmatist rather than an ideologue, it seems
more reasonable to just do sequence by doing things in sequence, rather than
forcing yourself to do unnatural contortions."_

"You have to do things my way, or you're not pragmatic!" seems to be your
dogma.

Reifying actions in a way that lets you talk _about_ them in the same way you
talk about the rest of your data is sometimes a very useful thing.

~~~
AnimalMuppet
> "Chaining actions with bind is the only way to combine actions" in Haskell
> is more strongly motivated by keeping things sane in the face of non-strict
> semantics than by a "functional straight-jacket".

OK, if you have non-strict semantics (by which I presume you mean non-
sequential), then you need some way to make things sequential when they have
to be, and you have no ordinary (non-jumping-through-hoops) way to make them
so.

> "You have to do things my way, or you're not pragmatic!" seems to be your
> dogma.

Shoe's on the other foot. Haskell's the one that insists that I _have_ to do
it Haskell's way. I complain, and you accuse _me_ of being dogmatic. Doesn't
work that way.

But I suppose you'd say that I have the choice to not use Haskell, so stop
complaining. And in fact, I take that choice, precisely because I consider the
language's dogmatism to be less pragmatic (and therefore useful) than a multi-
paradigm approach.

~~~
dllthomas
_" if you have non-strict semantics (by which I presume you mean non-
sequential)"_

[http://en.wikipedia.org/wiki/Strict_programming_language](http://en.wikipedia.org/wiki/Strict_programming_language)

 _" Haskell's the one that insists that I have to do it Haskell's way."_

... when you're writing Haskell. But _I_ am the one who sometimes wishes I
could manipulate actions in that way when I am writing C.

 _" But I suppose you'd say that I have the choice to not use Haskell, so stop
complaining."_

I'm saying that it obviously doesn't make pragmatic sense to require things in
contexts where they don't make sense, but that 1) some things can make sense
in more contexts than you might think, and 2) that you would do well (for
pragmatic reasons) to actually learn about this stuff before deciding you
don't need it.

~~~
AnimalMuppet
> I'm saying that it obviously doesn't make pragmatic sense to require things
> in contexts where they don't make sense...

Absolutely.

> you would do well (for pragmatic reasons) to actually learn about this stuff
> before deciding you don't need it.

I keep learning about it. I still haven't seen any need for it. But then, my
whole career is in a context where it doesn't make sense...

~~~
dllthomas
_" But then, my whole career is in a context where it doesn't make sense..."_

Well, like I said, applicability can be occasionally surprising. What is your
background like?

~~~
AnimalMuppet
Embedded systems. It's all about driving external hardware, and much of it
_has_ to be sequential.

~~~
dllthomas
Gotcha. I certainly agree (albeit with low confidence - never sure what
someone somewhere has done) that would make no sense as a GHC target. But that
doesn't mean the concepts necessarily have no applicability. As I said, I've
found myself wishing for some of Haskell's capabilities while writing C. That
said, when the usefulness is subtle it's probably not the place to start. I'd
dig deeper into some of the other monads first and basically forget about IO
until you actually want to code in Haskell.

Incidentally, you can write Haskell to write your embedded C:
[https://hackage.haskell.org/package/atom](https://hackage.haskell.org/package/atom)

I haven't actually played with it, but understand it's used in production.

------
dllthomas
_' there’s no such thing as the “IO monad” or the “List monad”'_

I don't think I agree (depending on just what is meant by "such thing as")...
I would say there is such thing as "the IO monad" in the same sense as there
is such thing as "the rational field" or "the Z/5 group". It's a particular
example of a more general algebraic structure, and you'd use the phrase when
you're talking _particularly_ about the structure as it occurs in that
instance.

------
kinofcain
Further evidence for my hypothesis that everyone who has ever understood
monads has gone on to write a blog post trying to explain them.

~~~
chocolateboy
... and failed:

> Once you understand what monads are, and why they exist, you lose the
> ability to explain them to anybody. -- Douglas Crockford [1]

[1]
[http://www.youtube.com/watch?v=dkZFtimgAcM](http://www.youtube.com/watch?v=dkZFtimgAcM)

~~~
marcosdumay
How can one lose it? Before understanding it, one also has no ability to
explain.

