Doug Beardsley (mightybyte) is a very prominent Haskeller. A maintainer of the Snap Web Framework for Haskell and Co-organizer of the NYC Haskell group. Definitely worth reading his stuff. Great tutorial as well!
Cool tutorials. I think it's much more effective to start with learning functors and applicatives before monads. I'm surprised at the number of tutorials aimed at teaching people monads who don't yet understand the more basic type classes.
>I think it's much more effective to start with learning functors and applicatives before monads. I'm surprised at the number of tutorials aimed at teaching people monads who don't yet understand the more basic type classes.
There is a point at which you can just follow along with the types as you learn Monads, but it's not terribly satisfying without context and still requires understanding _the types_. That's pretty hard to do if you aren't comfortable with higher kinded types and typeclasses. Functor and Applicative let you break the problem down a bit more. We do Monoid and Semigroup before Functor so they get accustomed to seemingly very abstract typeclasses before coping with higher kinded types + seemingly-abstract typeclass. Prior to _Monoid_, we explain kinds and higher kinded types.
This approach has made it so the book works a lot more effectively; frequently, but also makes it longer. Lots more code, examples, and exercises.
I've wondered that myself. I think the reason might be monads are used to represent IO computations and state mutation so people are interested in jumping straight into that. Honestly I use functor as much/more than I use monad in my day-to-day code which supports your statement here.
Coming at this from a mathematician's perspective, it's complete madness to learn what a monad is before learning what a natural transformation (and therefore a functor) is. I would also consider it somewhat eccentric to do monads without learning what an adjunction is, since adjunctions are basically why we're interested in monads in the first place.
Having been mildly disappointed by the simplicity of monoids, after intimidation from the complexity in maths, i expect that something like an adjunction is something already known to a commoner in any case, just that the vocabulary, particaularies and relations to the concept in question are not always obvious.
Monoids really are simple things. Monads are a bit less so, but they're still fairly simple objects (as evidenced by the fact that they have a short description, "monoids in the category of endofunctors", even if most people don't know what that means).
Adjunctions turn up all over maths, but I've been trying for a while to come up with an example which programmers (as opposed to mathematicians) would quickly understand. Broadly speaking, they represent "the leanest way to add a particular structure to something", but of course that's pretty useless for understanding them!
The significance of monads in programming is entirely because of the adjunction between the category of types and "pure" functions and the category of types and "monadic" functions (i.e., the Kleisli category of the monad). A monad is used to encode the latter in terms of the former via the Kleisli adjunction (whereby monadic maps from FX to FY correspond to pure maps from X to GFY, with the monad GF thus arising from an adjunction F -| G [where F can be taken to be identity on objects in the case of interest]).
If you're going to talk like that, stay far, far away from anyone who is trying to learn monads.
I assert that most people coming to Haskell do so because "I hear Haskell and/or FP is cool, I'll try to learn it" rather than "Category theory is so cool, wouldn't it be awesome to program that way". What you said may be true, as the theoretical foundation for why monads are useful, but for someone trying to learn to program in Haskell, what you said is the last thing they need to learn about monads.
That comment of mine wasn't the spiel I'd give to someone first trying to learn about the typical use of monads in a programming context, any more than I'd lecture a beginning programmer on the general theory of commutative rings while introducing integer and floating-point arithmetic (the latter not actually comprising a commutative ring...).
But teaching the use of monads to unfamiliar programmers wasn't my goal in that comment. I was just pointing out the accurate response to "Adjunctions aren't highly relevant to programming".
I'm not very familiar with category theory and can't really make heads or tails of what you're writing there, but I think the idea behind the statement that "adjunctions aren't highly relevant in programming" is to say that there isn't a huge amount of immediate utility of adjunctions as a programmer. On the other hand, programmers use monads all the time (even if they don't realize it, which is the most common case, as the monad in question is the evaluation of the imperative language they're writing in). Of course, to be honest, I wouldn't know an adjunction from a hole in the ground, so perhaps the same is true for adjunctions -- but I've never heard of them so I'm assuming that's not the case. Either way, what makes monads worth understanding is precisely how useful they are in day-to-day, real-world programming, and in particular understanding how they're used in Haskell is practically essential for understanding almost any extant Haskell code.
The purpose of that comment is to note precisely the same thing applying to adjunctions as you note applying to monads: programmers use adjunctions all the time even if they don't realize it.
"I've never heard of them so I'm assuming that's not the case"? Well, hey, most programmers have never heard about monads either. Explicitly having heard of a thing is, by definition, not a requirement for it to be something which one "use[s]... all the time (even if they don't realize it...)".
[I'm not saying everyone needs to go out and learn about adjunctions. But they're in exactly the same area as monads in terms of their applicability as a concept to programming. It's weird to consider the one a down-to-earth, comes-up-all-the-time notion and the other some airy-fairy academic construct.]
Hi, author here. Thanks for the feedback. I definitely get your point. I thought about it and there are a few reasons I went the way I did. 1. I decided that functors are straightforward enough to not really need significant special treatment. 2. Applicatives are much less commonly used than monads (see IO etc), so I thought it would be more desirable to hit the bigger use case first without getting side tracked on applicatives. 3. I feel this progression kind of has history on its side since Applicative wasn't a super class of Monad until very recently.
That being said, I'm very open to being convinced otherwise and pull requests carry a lot of weight with me. If someone reorganized the material in the way you suggest and it had a nice flow, there's a decent chance I would accept it.
I found a math background is a disadvantage for learning Haskell, since most mathematicians don't really use a lot of category theory. Lately that is changing,
http://math.stackexchange.com/questions/1617592/is-set-prime...
There's a lot of confusion on how the math version of "functor" or "monad" maps to the CS definitions.
I don't quite understand the relevance of the stackexchange link. Are you just pointing out that some mathematicians sometimes discuss categories, with this as an arbitrary example? I don't think anyone doubted that.
Something that doesn't help the Math->CS understanding of Functors is, for example, that languages like C++ use "Functor" to mean other things (function pointer in this case).
The C++ use of the word "functor" goes back to the original use of the word "functor" by Rudolf Carnap (to mean something like a word which combines with other words as arguments to produce a full term; a word that acts function-like, basically).
Saunders Mac Lane took the word "functor" from Carnap and gave it a particular definition in category theory (when founding category theory with Samuel Eilenberg). The ML languages and Haskell use the word "functor" in reference to this category theory sense of the word.
But category theory is not actually where the word "functor" originated. So perhaps we shouldn't say that C++ got its use of the word wrong, but rather, that there were simply two independent paths of evolution of technical uses of the word since its original creation by Rudolf Carnap for use in philosophy of language.
In any case it's annoying to have different languages adopting the same word to mean vaguely related but actually completely different things. I suspect that is why a lot of tutorials about Monads skip talking about Functors altogether which ends up making the whole thing more confusing.
It's not though, in C++ a functor is generally something which defines the operator which lets you treat it as a callable.
(a thing which acts like a function)
Though the suppose the dissonance in naming point still applies.
People always say that monads are not that hard and you don't need to understand category theory to understand monads, but since people still keep writing tutorials for them (and thus imply that we have yet to see a perfect one that clearly explains everything you need to know about monad), I sometimes wonder that if beginners should just start from category theory.
I know loads of category theory, but when I tried to find out how monads were used in computer programming I was disappointing to find that no one has written a "Monads in Haskell for Category Theorists"tutorial. :-(
Hi, I was assuming that people would do their playing around and answer checking in ghci. MCPrelude does not export putStrLn because it is an IO function, which is a monad and I specifically wanted to hide all the prelude's monad stuff. I suggest loading your file in ghci with "ghci Set1.hs". Then you can just type "fiveRands" at the ghci prompt and it will show you the values.
Thanks! It would be great to walk through this, in the same way that it shows the shell commands for installation under "Getting Started."
I hardly ever use the repl because I prefer to keep my tests around. I'm sheepish to admit this, but I only just now learned that you can pass a file to ghci.
Ignore the instructions and grab putStrLn if you need it in order to check your work. The instructions about not using other modules are there to avoid you "cheating". Looking at your work is definitely not cheating and will not prevent you from learning :).
Also, just typing "fiveRands" and hitting ENTER at the repl will show you the value of fiveRands (or any other expression).
To be more precise, any other expression with an appropriate type. That's `a` or `IO a`, where `a` is an instance of `Show`.
Most things that can reasonably be Shown already have a `Show` instance, but some things (like functions) can't really.
This is relevant when the REPL shows an error like:
<interactive>:2:1:
No instance for (Show (t0 -> a0))
(maybe you haven't applied enough arguments to a function?)
arising from a use of ‘print’
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
it doesn't look like their prelude has any stdout printing functions, so it's probably easiest to test your code in a repl. you can check what functions they do give you by looking at the stuff before the "where" here: https://github.com/mightybyte/monad-challenges/blob/gh-pages...
as for verifying your results, they give you the product of the 5 numbers at the bottom of the page (since you're starting from a predetermined seed, the 5 numbers you generate are known)
Great. I was wondering if anyone is interested in writing a book or a blog titled something to the effect of "all the brutal concepts in the languages you want to learn or respect." For example, monads in Haskell, macros and continuations in Scheme...Maybe languages like C, Forth, Prolog, Smalltalk etc also have such arcane concepts that "scare" people??
I don't know about scaring people, but many programming languages have concepts that are best demonstrated with small examples that make people say "whoa".
For example, it's amazing that append() in Prolog can be run "backwards" from the concatenated result to yield all the lists that can be concatenated to produce it. Or that the monadic bind operator in Haskell (>>=) can be defined in terms of join and fmap, or that ($) = id.
Programming languages have idiomatic expressions, and learning why they do what they do can produce enlightenment. It's no accident that C supports syntax like 3["hello"]. It looks mysterious, but not when you know that x[y] == *((x)+(y)) by definition. APL was especially rich in idiomatic expressions; I suppose that it's a sign of having easily composed primitives.
No you don't need a specific language to implement any functionality that can be implemented by a turing-complete language.
I watched Crockford's monad talk [1]. He used javascript. The only problem with that talk is that he spent about 10 seconds or less explaining what a monad is (and the rest of the talk on implementation issues and his own perspective, etc, etc).
I'm still waiting for a good monad discussion without CT or Haskell. (this [2] and this [3] look promising, both in python)
It's true that you don't need to know Haskell in order to learn about monads, but Haskell is a perfectly reasonable language in which to write a monad introduction.
Haskell is good for learning about monads for the same reasons monads tend to be heavily used in Haskell, but not in other languages. Monads are both part of Haskell's standard library, and have very useful special syntax (do-notation). Writing out monadic code explicitly gets to be a huge pain when using monads in another language. Typeclasses also make it convenient & easy to write code that's generic over any monad.
Hi, I'm sorry you feel that way. Maybe you just aren't my target audience. That being said, Crockford's explanation of monads in that talk was overly simplistic and misses much of the point of the benefit that you get from them in a language like Haskell. And if we're being honest here I think it's safe to say that most programmers wouldn't have even heard of monads if it wasn't for Haskell. I gave a talk at the NY Haskell meetup a few years ago that specifically addresses Crockford's talk in a little more detail [1]. That talk might be about the level you're looking for. There is some Haskell code, but most of the talk should make sense to someone not familiar with Haskell.
That may be true in principle, but I have been unable to find any resource ever that explains them well. Presumably this is because I don't know Haskell and the only good explanations are in that language.