Hacker News new | ask | show | jobs
by Retra 3942 days ago
That's something you have to learn to do. It's like asking "where is the stack?" when you're just calling functions. If you don't develop some skill for seeing how your code implements underlying abstractions, you will be missing out. You can program without knowing what a stack is. But if you want to solve a problem using a stack, it helps to know that your function call stack can be 'overloaded' to solve stack problems, rather than building an explicit stack data-structure yourself.

It's harder than it has to be, but it's also more powerful than it has to be. Because against the right kind of problem, it'll be just barely powerful enough.

1 comments

What I meant was something different. The difference is that saying that "IO is a monad" is wrong in the mathematical sense too. IO is not a monad - the combination of (IO, bind, return) is the monad. It only makes sense to say the above in Haskell where there can be only one instance per type.

The set of natural numbers N is not a monoid; {N, +, 0} is a monoid. The set may, at best, be "monoidal" (i.e. there exists associative binary operator <> and a set member ZERO such that for all elements of the set, ZERO <> x == x <> ZERO == x).

So as a beginner, it doesn't even help to try and read the "70 years of literature" on the subject, because what you read there does not match (I'm reading about a set, an operation and an element of the set - and all I have here is the actual set. Where are the operation and the element? Oh they are defined and passed implicitly for the type. Oh so the type isn't the monoid, its at best MONOIDAL)

"[T]he combination of (IO, bind, return) is the monad. It only makes sense to say the above in Haskell where there can be only one instance per type."

This is very important, and something that took me a bit to grok, and definitely got in the way of understanding for a while.

One thing you can do - and I don't know whether it makes sense to teach it this way - is think of the typeclass constraints as actual arguments (absent optimizations, that is literally the case anyway - GHC passes instance dictionaries). In that case, "the monoid" is that dictionary, and the type referenced is the carrier set, and a value of that type is an element of the carrier set.

> What I meant was something different. The difference is that saying that "IO is a monad" is wrong in the mathematical sense too.

It's relatively common to refer to the underlying set as a monoid (or whatever structure you're talking about) if it's clear from the context what the operations are, though.

> The set may, at best, be "monoidal" (i.e. there exists associative binary operator <> and a set member ZERO such that for all elements of the set, ZERO <> x == x <> ZERO == x).

That's a pretty useless definition, though, as every non-empty set trivially satisfies that condition (just pick any element as the zero element, and let the binary operation be the constant mapping to that element). Also, “monoidal” usually means a monoidal category, which is something very different from the underlying set of a monoid altogether.

> It's relatively common to refer to the underlying set as a monoid (or whatever structure you're talking about) if it's clear from the context what the operations are, though.

Relatively common even outside Haskell?

> Relatively common even outside Haskell?

It's common throughout mathematics. So common, in fact, that there's even a wikipedia article on the phenomenon[0].

“Common examples occur when speaking of compound mathematical objects. […] Similarly, one often refers to a group (G, \star) as simply G when the group operation is clear from context.”

[0] https://en.wikipedia.org/wiki/Abuse_of_notation

Fair enough. But I don't think its surprising that it may lead to confusion when beginners study the subject.