Live data from Hacker News

Functor, Applicative, and Monad

typeslogicscats.gitlab.io

61–70 of 125 posts

Re: Functor, Applicative, and Monad

#61

Earlier quoted context omitted.

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 info…

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…

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.

Re: Functor, Applicative, and Monad

#62

Earlier quoted context omitted.

You claim that OCaml programmers are already versed in category theory but that’s not correct. The first exposure usually comes with concurrency libraries such as Lwt which isn’t very old nor in the standard library, and it provides syntax sugar so you can start being productive right away. You can write perfectly fine production OCaml programs without knowing what a monad is. Some may, but a lot of OCaml devs don’t…

This is correct, and in contrast to Haskell, where monads are a core part of the language (they are used in the definition of do-notation and list comprehensions) and currently the mainstream way to do IO.

This is misleading. There's no place in the specification of Haskell that specifically defines monads as part of the language. They aren't a language feature. They are a pattern which happens to be expressible in Haskell, and which is supported by libraries:

"Haskell's built in support for monads is split among the standard prelude, which exports the most common monad functions, and the Monad module, which contains less-commonly used monad functions. The individual monad types are each in their own libraries and are the subject of Part II of this tutorial."

https://wiki.haskell.org/All_About_Monads#Monad_support_in_H...

The fact that monads are used to implement parts of the language doesn't make them a core part of it. Techniques used in implementation aren't the same as language features.

Re: Functor, Applicative, and Monad

#63
post #28

Earlier quoted context omitted.

The point is that Monad, Applicative and Functor are well defined interfaces with laws (properties) you can count on. They are in fact much better, more precisely defined than classic design patterns. And in expressive programming languages (that support higher kinded types or that at least let you encode such types) you can also describe generic code that works over any applicative or monadic type. Having reusable f…

> Having reusable functions that work just as well on lists, maybe/option, reader, io / promise or what have you means these type classes do a very good job at abstracting over data types. These are the purest forms of abstraction. This is where I get kinda lost. Can you give an example of such a reusable function that works for all these things which does something valuable?

The simplest but still most versatile one is probably fmap (also knowns as ) which lets you use a function on whatever is inside the burrito:

(+1) Just 1 → Just 2 (+1) getIntFromThatUserThatOnlyTypes1 → IO 2 (+1) [1,2] → [2, 3] ((+1) ask) 1 → 2

Want let a function eat several burritos without making a mess? Keep your burritos apart with >:

take Just 2 > Just "abc" → Just "ab"

etc.

You can be quite productive without moving past the burrito analogy.

Re: Functor, Applicative, and Monad

#64

Earlier quoted context omitted.

You claim that OCaml programmers are already versed in category theory but that’s not correct. The first exposure usually comes with concurrency libraries such as Lwt which isn’t very old nor in the standard library, and it provides syntax sugar so you can start being productive right away. You can write perfectly fine production OCaml programs without knowing what a monad is. Some may, but a lot of OCaml devs don’t…

This is correct, and in contrast to Haskell, where monads are a core part of the language (they are used in the definition of do-notation and list comprehensions) and currently the mainstream way to do IO.

By this definition Monads are also a core part of C#, they're not used to do IO but the async/await, IEnumerable, null-safe operators ('?.') are all implementations of Monads (not by coincidence), and above all you have the Linq syntax that you can extend to all of them and any other Monads you care to define.

Yet I imagine most C# programmers have little to no formal understanding of Monads (although quite a few probably do at least know about the link).

Re: Functor, Applicative, and Monad

#65
post #28

Earlier quoted context omitted.

The point is that Monad, Applicative and Functor are well defined interfaces with laws (properties) you can count on. They are in fact much better, more precisely defined than classic design patterns. And in expressive programming languages (that support higher kinded types or that at least let you encode such types) you can also describe generic code that works over any applicative or monadic type. Having reusable f…

> Having reusable functions that work just as well on lists, maybe/option, reader, io / promise or what have you means these type classes do a very good job at abstracting over data types. These are the purest forms of abstraction. This is where I get kinda lost. Can you give an example of such a reusable function that works for all these things which does something valuable?

Here is a quick real world example: You are working on a compiler, type checking statements one by one. You come across a function call and to type check that, you first need to type check the argument expressions to get their types and abort the whole thing if they don't make sense. You use a `Maybe` type to model the result of type checking the argument expressions: The result is either `Nothing` (in case of failure) or `Type` (in case of success). `Maybe` is kinda similar to a nullable type in other languages. In Java you would now make an if-statement for each argument and check that the result of type checking wasn't null; Very annoying. Luckily for you, `Maybe` is an `Applicative` so you can just use the `traverse` function to do this for you automatically: The argument iteration will stop automatically and return `Nothing` if any single argument type check returns `Nothing`. You are happy with your compiler, but your colleague says it sucks, because they can never know what went wrong. To fix this you replace `Maybe` with the `Either` type. Instead of returning `Nothing` in case of failure you can now return an `Error`. Dreadfully you set about to refactor your whole codebase, only to realize that `Either` is also an `Applicative` and has the `traverse` function. Everything works just as before. Your colleague still isn't satisfied: Your compiler always aborts at the first error but they would like to see all the errors in the input at once. Again, you replace `Either` with the `Validation` type, which accumulates errors in independent computations. `Validation` is also an `Applicative` and everything still works as before. You just got your error accumulation for free without large refactoring.

Re: Functor, Applicative, and Monad

#66
post #49

Earlier quoted context omitted.

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.

Re: Functor, Applicative, and Monad

#67
post #10

Earlier quoted context omitted.

I have never heard of Euterpea, nor have I seen the rest of your code, but I suggest you refactor your slightly convoluted code like this: notePlayer notes octs dur = musicSeq $ notes octs pure dur Coincidentally, this might be a testament of the power of parametric polymorphism and equational reasoning.

My favorite part about Haskell is how you can know literally nothing about the domain and make meaningful changes to programs regardless thanks to local reasoning. That's really one power of functor/applicative/monad - if you understand their interfaces, you can work with new unfamiliar types that have these instances without much effort at all.

It's literally a meaningless change! :-) All refractorings at meaningless changes, by definition and design.

Purity's power is that beautiful meaningless changes are safe.

Re: Functor, Applicative, and Monad

#68
post #28

Earlier quoted context omitted.

> Having reusable functions that work just as well on lists, maybe/option, reader, io / promise or what have you means these type classes do a very good job at abstracting over data types. These are the purest forms of abstraction. This is where I get kinda lost. Can you give an example of such a reusable function that works for all these things which does something valuable?

The simplest but still most versatile one is probably fmap (also knowns as ) which lets you use a function on whatever is inside the burrito: (+1) Just 1 → Just 2 (+1) getIntFromThatUserThatOnlyTypes1 → IO 2 (+1) [1,2] → [2, 3] ((+1) ask) 1 → 2 Want let a function eat several burritos without making a mess? Keep your burritos apart with >: take Just 2 > Just "abc" → Just "ab" etc. You can be quite productive without…

No. If you attempt to write monad-generic code using the burrito analogy you will inevitably write broken code, causing serious problems for other users and/or your future self.

Burritos may be a good analogy for some subset of monads, e.g. collections, but they are not a good analogy for monads in general: the function you pass to fmap may be executed now or later, zero, one, or many times, before or after a function you pass to a later fmap.

Re: Functor, Applicative, and Monad

#69
post #31

Earlier quoted context omitted.

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 info…

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…

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?

Re: Functor, Applicative, and Monad

#70
post #49

Earlier quoted context omitted.

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 incident…

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.
Post reply on HN