I am the author of this submission. I have strong opinions about functor and monad tutorials, and here are my thoughts:
Back when I didn't understand what a monad was, I would read a bunch of tutorials and get confused by the analogies and examples. For example, I would get confused by comparisons to "boxes," or I would think that Maybe was the definition of a monad, or that IO was the definition of a monad.
The information in the tutorial that you link seems to be all correct. However, it's too "jumpy" for my tastes. The tutorial talks about "contexts," but doesn't really explain what a "context" is, except for making a comparison to "boxes." I get that a functor is an abstract idea, so explaining it in an understandable way is difficult. However, I wish that the article would discuss type constructors, because the idea of mapping types to types is an important part of the definition of functor. Without this explanation, I imagine that the comparison to "boxes" would have given the past me the wrong impression of what a functor is.
In my tutorial, I sought to teach the actual definition of a functor, applicative, and monad. I explain that a functor maps types to types and functions to functions in a way that preserves composition and identity, that an applicative preserves the product, and that a monad is characterized by a "join" operation that "flattens" the data and a "return" operation that "wraps up" the data. I actually would have preferred to explain the actual category theory, but I felt that it would be too intimidating, and so I attempted to convey the ideas in a non-category-theory way. With my current understanding of functor, applicative, and monad, I believe that if one doesn't learn their actual definitions, one doesn't truly understand them. I guess that I wanted my tutorial to be more rigorous.
However, I am not an expert on teaching, so maybe I'm taking the wrong approach.
As Doug Crockford once said "In addition to it begin useful, it is also cursed and the curse of the monad is that once you get the epiphany, once you understand - "oh that's what it is" - you lose the ability to explain it to anybody." [1]
I think someone who is a beginner or just want to use Functor / Applicative / Monad without mastering underlying Category Theory, boxed model seems good enough. However, if you are creating own monads, then of-course we need to understand monadic laws. Every programming language has monad of some sort e.g. Optional in Java. To use optional chaining, I may not need to know all details but only how `flatMap` works. Maybe I am wrong too :).
Losing the ability to explain it is good, because the explanations are wrong.
The best modern advice about moands is that you don't learn them by explanation of the monad in isolation, you grok them by experience with examples and study of the formal definitions. This applies to a lot of Haskell (and mathematics in general), that has the ability to provide precise concise implementations of very powerful, general concepts.
Monad tutorials for newbies are like explaining quantum mechanics to someone who hasn't learned anything about optics or electricity or complex numbers yet - a bunch of false, meaningless metaphors.
Thank you for taking what seems to be an interesting approach to explaining these concepts.
> I use OCaml in this tutorial, with some occurrences of Haskell.
> My intention is for anyone familiar with the basics of typed functional programming to be able to follow along.
I don't know OCaml or Haskell and I got lost very early on due to the unfamiliar syntax. Do you think your explanation would be easy to translate to a more widely known language like Python or C?
Shrugs Well, Python is dynamically typed and C doesn't really have good polymorphism or first-class function support. Both polymorphism and first-class functions (with closures) are important for understanding functors, applicatives, and monads.
I admit that I'm more fluent in OCaml than I am in Python or C, so please correct me if I'm mistaken.
Python and C would indeed be unsuitable. Maybe Rust (quite OCaml-like, but with a more C-like syntax) or Java/C#/Kotlin would let you present these ideas with a more "mainstream" syntax?
You can do it in Scala which has powerful type support.
The problem with other languages is that they lack the support for the higher order types, so the implementation is dishonest or you have to build up an API (new embedded minilanguage) to express them, which is a lot of work and a distraction.
And, the result tends to be very cluttered with syntax junk, as you can see in Scala and Functional Java.
Which incidentally is why people generally don't use these ideas in Java code. You can use these design ideas in your Java architecture, but not directly express them in your Java code.
OCaml also lacks higher-kinded types. As far as I can tell, anything you can do in OCaml you can also do (perhaps verbosely, though less so in more recent versions) in Java.
OCaml have HKT, it's in the module part of the languiage, it's just verbose.
And OCaml's module language is much more powerful than Java, since module language is a dependently typed language. You can't, say, pass a class including a type for another class in java.
Hi! Reading your tutorial I wanted to leave a quick comment on HN and was worried you wouldn't see it. Nice to see you're present!
Thanks, I liked reading it a lot. It's a good refresher, since I never use haskell but have read about this a couple of times.
The tutorial appears great on mobile, so I was able to refresh my memory very quickly. However, the code boxes had a very small font. I think this could me easily fixed with fome html-fu on the meta tag or the sizing of the box/font.
I also think that it would be great it you could explain at the end what is a counterexample input for the small haskell program. For example, if the user inputs a file that doesn't exist, then the readFile returns Nothing, then putStrLn returns Nothing. There's a sentence in the conclusion that explains that monads are nice to use but not why. I understand that it deals with values inside contexes, but in practice how does it affect development?
Thank you for the praise. For me, the inline code has about the same font size as the surrounding text, maybe smaller, and the block code has a bigger font. Is it possible for you to send me a screenshot?
I'm a little confused by your last paragraph. My last code example doesn't use readFile and putStrLn, and it isn't written in Haskell?
Back when I didn't understand what a monad was, I would read a bunch of tutorials and get confused by the analogies and examples. For example, I would get confused by comparisons to "boxes," or I would think that Maybe was the definition of a monad, or that IO was the definition of a monad.
The information in the tutorial that you link seems to be all correct. However, it's too "jumpy" for my tastes. The tutorial talks about "contexts," but doesn't really explain what a "context" is, except for making a comparison to "boxes." I get that a functor is an abstract idea, so explaining it in an understandable way is difficult. However, I wish that the article would discuss type constructors, because the idea of mapping types to types is an important part of the definition of functor. Without this explanation, I imagine that the comparison to "boxes" would have given the past me the wrong impression of what a functor is.
In my tutorial, I sought to teach the actual definition of a functor, applicative, and monad. I explain that a functor maps types to types and functions to functions in a way that preserves composition and identity, that an applicative preserves the product, and that a monad is characterized by a "join" operation that "flattens" the data and a "return" operation that "wraps up" the data. I actually would have preferred to explain the actual category theory, but I felt that it would be too intimidating, and so I attempted to convey the ideas in a non-category-theory way. With my current understanding of functor, applicative, and monad, I believe that if one doesn't learn their actual definitions, one doesn't truly understand them. I guess that I wanted my tutorial to be more rigorous.
However, I am not an expert on teaching, so maybe I'm taking the wrong approach.
See my Reddit comment: https://www.reddit.com/r/programming/comments/cy35zz/functor...