Live data from Hacker News

Functor, Applicative, and Monad

typeslogicscats.gitlab.io

81–90 of 125 posts

Re: Functor, Applicative, and Monad

#81

I don't think this article is very useful. It doesn't adequately provide an introduction to OCaml code (or adequately explain what a given code snipped is doing) and yet frequently defers to just code to explain a concept. It's an unrealistic expectation to expect an unfamiliar reader to simultaneously infer what a particular code snippet is doing then also go a level deeper and understand the concept that is trying…

> if you can already read OCaml code you already understand these concepts.

This is a mistake. There are plenty of functional programmers who aren't familiar with these concepts. It's hardly a topic in introductory OCaml...

Re: Functor, Applicative, and Monad

#82
post #54
post #14

I should learn to read Haskell one of these days. Not today though.

"Learn You a Haskell" is sparse on theoretical foundations. I made it halfway through the book feeling like I only had a superficial understanding of the language. If you are interested in a rigorous or systematic approach I recommend "Haskell Programming from First Principles".

I think both are great books, but the book you choose is secondary in importance to the amount of time you spend just bashing your head against it until it starts to make sense.

Re: Functor, Applicative, and Monad

#83
post #35

I don't think this article is very useful. It doesn't adequately provide an introduction to OCaml code (or adequately explain what a given code snipped is doing) and yet frequently defers to just code to explain a concept. It's an unrealistic expectation to expect an unfamiliar reader to simultaneously infer what a particular code snippet is doing then also go a level deeper and understand the concept that is trying…

OCaml (Reason) was my entry point into Typed FP (after a few failed attempts at learning Haskell). The best thing about OCaml is that it allows side-effects, so one can go a long way without having to touch advanced FP. It is only recently that I've started getting comfortable with concepts cogently explained in this post, so to me it is quite valuable. As an aside, I think OCaml/Reason/Elm should become the de-facto…

Similar for me. Tried to get into typed FP multiple times with no luck, but then I built a couple of web services with F# + Giraffe and an app in Bolero. It let me take my time getting into FP concepts and incorporate them along the way

Re: Functor, Applicative, and Monad

#84
post #40

Maths is what you get when you limit all your variable names to single letters.

I used to think the way you do (or the way I'm inferring you think), especially coming from the OO world to functional.

But, functional programming is really about programming with types, not named things, and so a lot of the time we work with much smaller functions that are expressions. It should be trivial to follow the intention without explicit names.

Having terse and concise names can make it much easier to read if you're following the types. Occasionally, if a piece of code is more challenging to read, I may use single word variable names, but mostly it's trying to get the names out of the way of the types and operators.

For example, if I have a type (where `a` is generic):

    a -> bool
Then this can only be a predicate function. If it's provided as an argument to a function, I'll call it `f`, not `predicate`, because the type itself is the documentation.

It's definitely a mindset change for a different approach, functional programming is much more about function composition, whereas imperative is about a list of steps to perform, and so that composition is much more about whether the types fuse or not, the names become slightly less relevant, especially for general purpose library functions.

Personally, I feel it helps. But this is probably one of those subjective things like tabs vs spaces.

(spaces are correct)

Re: Functor, Applicative, and Monad

#85
post #48

Earlier quoted context omitted.

It's important not to think of types as just sets of values, because types are more semantic than that; two quite different types might have the same underlying values but they're different types because you use them to mean something different. A typeclass is one or two levels higher than a type, and yes, for a type to conform to a typeclass usually means that that type supports particular operations in a way that c…

Seems similar to type traits in Rust. I skimmed through "Category Theory for Programmers" and it's mentioned this thing is mainly about composition. Composing functions? So you've got a trait (say Functor) that is meant for functions. You know something about functions that have this trait, so you can exploit that knowledge to create compositions of those functions. So then in theory you can write algorithms with as…

Rust traits are pretty much typeclasses. I don't agree with "this thing is mainly about composition" so I don't know what to tell you there. Functor isn't meant for functions, it's meant for types, or rather type constructors (types of kind * -> *).

Higher-kinded types are just "what if type parameters could be parameterized types" - I'd argue that from a certain perspective a language that allows them is simpler than one that doesn't. If you know Rust then you can hopefully see that Future#and_then, Option#and_then, and Result#and_then are in some sense "the same" function (and that function is the heart of the usual definition of a monad). But if you try to write some generic code in terms of and_then that could work for Future, Option, and Result, you'll find that Rust's type system isn't sophisticated enough to let you do that (even if you try to define a custom trait for it).

More generally, the way I tend to see applicatives and monads is: what if you could write an algorithm that worked generically for any secondary concern. What if you could write functions that incorporated what the AOP people call "pointcuts", in a generic way, but without having to step outside the type system and break the normal way that code and functions behave? But you absolutely need higher-kinded types before you can even start to talk about this, because you need to be able to talk about "wrapper" types in a generic way, which you can'd do if you can't have generic (parameterised) types as parameters.

Re: Functor, Applicative, and Monad

#86

Earlier quoted context omitted.

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

A pedantic distinction without a practical difference. Everyone who learns Haskell learns about Monads.

Re: Functor, Applicative, and Monad

#87
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?

This is mostly useful for reusable boilerplate. For example, if I have a list and want to map over it with a function, I can call normal `map`. But if I want to map over it with a function that doesn't return a normal value, I can get something weird. With promise, for example, I might end up with a list of promises, where what I want is a promise containing a list. If I didn't have monads, I would have to write a function that manually took each value out of the list, awaited it, and put that value into a new list that will be returned from that function.

In Haskell, that function is just called `mapM`, and it's consistent whether you're working with exceptional cases (Either String a), nullable cases (Maybe a), IO (IO a), Promises (Async a), or even weirder things.

This is actually a huge problem for the Java Streams API, because Java's checked exception feature is sort of like most monads. You can't call a function that throws an exception inside of a function that doesn't, except by using some weird incantation. (You can think of `try` as being a built in syntax for "running" the exception monad). Which means that you can't call an exception throwing function in `Stream::map`. Instead, you have to do something really ugly. https://www.reddit.com/r/java/comments/49yjqf/tunnelling_exc...

Re: Functor, Applicative, and Monad

#88

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…

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…

I wrote a very long and incomplete monad tutorial that primarily uses Python. It's very different from OP, but feel free to check it out.

https://github.com/lalaithion/MonadPaper/tree/master/out

Re: Functor, Applicative, and Monad

#89

I don't think this article is very useful. It doesn't adequately provide an introduction to OCaml code (or adequately explain what a given code snipped is doing) and yet frequently defers to just code to explain a concept. It's an unrealistic expectation to expect an unfamiliar reader to simultaneously infer what a particular code snippet is doing then also go a level deeper and understand the concept that is trying…

When I first learned Haskell it took a very long time before I started figuring out what monads, applicatives and category theory were, and even then I only ever took a deep dive into monads specifically, basically so that I could do side effects.

For a long time in the beginning I was just learning about the basics, like list manipulation functions, and typeclasses. There was quite a journey in between beginning Haskell and even starting to look at the learning material for monads/functors etc.

Re: Functor, Applicative, and Monad

#90

Earlier quoted context omitted.

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

[deleted]
Post reply on HN