The Monad Challenges: Jump start your understanding of monads
mightybyte.github.io
mightybyte.github.io
I agree, we did this in our book. We actually decomposed it pretty aggressively - http://haskellbook.com/progress.html
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.
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!
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.
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".
(honest question, just trying to find a simple, grokkable definition)
"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.]
I initially had problems understanding monads in Haskell having come from a math perspective.
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 this tutorial on Monads and Applicatives helpful http://adit.io/posts/2013-04-17-functors,_applicatives,_and_...
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.
The math definitions. These were invented by Saunders Mac Lane and Samuel Eilenberg back in 1945ish, about a year before ENIAC was built.
Though the suppose the dissonance in naming point still applies.
In mathematics, those things are just called "functions". :P
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.
For example, Set1 tells me to make a function fiveRands and then "check my answers;" how do I do that? I know enough Haskell to do something like:
main = putStrLn $ show fiveRands
but putStrLn is not part of MCPrelude so this doesn't compile, and the instructions say explicitly "Do not import any other modules."I'm excited to try these. Please add some more hand-holding to get me and others over the tooling and environment issues.
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.
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 itas 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)
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.
($) = id !?
< tries it out in Raskell/Ghci >I see now why it's true, but still... Whoah!! Thanks for that!
I think your suggestion would make a terrific online book.
https://www.manning.com/books/functional-programming-in-scal...
This is enough for me to reject this blogpost.
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)
[1] https://www.youtube.com/watch?v=b0EF0VTs9Dc
[2] http://www.valuedlessons.com/2008/01/monads-in-python-with-n...
[3] http://www.dustingetz.com/2012/04/07/dustins-awesome-monad-t...
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.
Couldn't any other language have a syntax like
thing.do(\x -> other thing(x)).do(
\x -> yet another thing(x)).do(
a function).do(
more stuff).do(
etc)
And then replace "\x -> whatever" with the local language's lambda syntax. The only time you get the painful nested parens is if you want thing.do(
\x -> f(x).do(
\y -> g(x,y)))
It's not too terribly bad.