Live data from Hacker News

Functors, Applicatives, and Monads in Pictures (2013)

adit.io

21–30 of 56 posts

Re: Functors, Applicatives, and Monads in Pictures (2013)

#21
post #15
post #2

Nice pictures, but I just don't get it. Sure, it's very easy for me to understand monads mathematically, what kind of structure are they. I don't need any pictures for that, the definition suffices for me. But that doesn't tell me what are they good for . We invent things for a reason, and I don't see the reason. Now I know the reason, it's been told to me many times (some way to wrap I/O while preserving functional…

I tried covering it (and showing there's a better way) in this talk: https://www.youtube.com/watch?v=449j7oKQVkc

That's an interesting talk. There's no good reason you should be getting downvoted.

Re: Functors, Applicatives, and Monads in Pictures (2013)

#22
post #2

Nice pictures, but I just don't get it. Sure, it's very easy for me to understand monads mathematically, what kind of structure are they. I don't need any pictures for that, the definition suffices for me. But that doesn't tell me what are they good for . We invent things for a reason, and I don't see the reason. Now I know the reason, it's been told to me many times (some way to wrap I/O while preserving functional…

It's not about I/O. It's about being able to handle cross-cutting concerns like logging, or error handling, or dependency injection, or async, with ordinary refactor-safe functions rather than global variables. http://m50d.github.io/2013/01/16/generic-contexts.html was my effort.

Re: Functors, Applicatives, and Monads in Pictures (2013)

#23

Off-topic, but why are Haskell's function signatures written like this? function_name :: Param1Type -> Param2Type -> Param3Type -> ReturnType To me that just makes no sense. There's no way to logically "read" it. The natural way would be "function_name converts a Param1Type into a Param2Type and then ... what?! Is this a chain of functions?" Why not have something sensible like this? function_name :: Param1Type, Para…

A function has ONE parameter and ONE return value. The trick is that these parameters and returned values may be tuples or functions themselves.

So we can have a function which takes a single parameter which is a tuple :

    function_name :: (Param1Type, Param2Type) -> ReturnType
Or we can have a function which takes a single parameter and returns another function:

    function_name :: Param1Type -> (Param2Type -> ReturnType)
Using implied operator precedence, the later is written:

    function_name :: Param1Type -> Param2Type -> ReturnType
And has to be distinguished from a function which takes a function as parameter:

    function_name :: (Param1Type -> Param2Type) -> ReturnType

Re: Functors, Applicatives, and Monads in Pictures (2013)

#24
post #20

Off-topic, but why are Haskell's function signatures written like this? function_name :: Param1Type -> Param2Type -> Param3Type -> ReturnType To me that just makes no sense. There's no way to logically "read" it. The natural way would be "function_name converts a Param1Type into a Param2Type and then ... what?! Is this a chain of functions?" Why not have something sensible like this? function_name :: Param1Type, Para…

Because you write functions like this in mathematics as well. What we usually see is something like this: f(x) = y But if you look at it carefully the function f is a mapping of the domain x to the range y (the arrow is f), written like so: x -> y Of course, the domain, being a set of all permissible values, is the type. So we write the type instead: type1 -> type2 Everything in Haskell is a function, and pure functi…

I don't understand one thing about this notation:

   fun :: A -> B -> C -> D
can be bracketed in a bunch of different ways -

   fun1 :: (A -> B) -> (C -> D)
   fun2 :: A -> (B -> C -> D)
etc. and don't these all mean different things?

fun1 would take a function and return a function, whereas fun2 takes an A and returns a curried function of B,C -> D.

Re: Functors, Applicatives, and Monads in Pictures (2013)

#25
post #20

Earlier quoted context omitted.

Because you write functions like this in mathematics as well. What we usually see is something like this: f(x) = y But if you look at it carefully the function f is a mapping of the domain x to the range y (the arrow is f), written like so: x -> y Of course, the domain, being a set of all permissible values, is the type. So we write the type instead: type1 -> type2 Everything in Haskell is a function, and pure functi…

I don't understand one thing about this notation: fun :: A -> B -> C -> D can be bracketed in a bunch of different ways - fun1 :: (A -> B) -> (C -> D) fun2 :: A -> (B -> C -> D) etc. and don't these all mean different things? fun1 would take a function and return a function, whereas fun2 takes an A and returns a curried function of B,C -> D.

Read:

   fun :: A -> (B -> (C ->D))

Re: Functors, Applicatives, and Monads in Pictures (2013)

#26
post #3
post #2

Nice pictures, but I just don't get it. Sure, it's very easy for me to understand monads mathematically, what kind of structure are they. I don't need any pictures for that, the definition suffices for me. But that doesn't tell me what are they good for . We invent things for a reason, and I don't see the reason. Now I know the reason, it's been told to me many times (some way to wrap I/O while preserving functional…

The reason that the Monad structure is interesting, in my view, is that it's simple and neatly captures the notion of a "computation" that we can compose in different ways. The core useful operator for monads in Haskell is >>=. It has the following type: m a -> (a -> m b) -> m b If you squint, this is like function application with a few extra m's thrown in. Here's normal function application for comparison: a -> (a…

> Well, the problem in Haskell is that it's a language of evaluating expressions at heart: executing effects makes no sense any more than it would in arithmetic.

You know what else doesn't make sense in arithmetic? Computation. I think it is important to wonder how come mathematical definitions of computation didn't come about until the 20th century[1] even though math has had most of its big breakthroughs (to date) by then (or, at least, there was no revolution in mathematics in the 20th century on the same scale as there was in physics). And yet, as advanced as math was, computation was only defined very late in the game. The reason is that, perhaps ironically, the concept of computation is absent from most of math, which is "equational".

But computation is the very core of computer science. So, for example, in arithmetic, 4 and 2+2 are the same thing because 4 = 2 + 2. So in arithmetic, equality means "sameness". But in computer science they are most certainly not the same, because the process of moving from one of the representation to the other is precisely what a computation does. Not only that, the process isn't even necessarily symmetrical, as moving in one direction may entail a much higher computational complexity than going in the other direction.

Any distinction between calculations and effect (other than actual IO) is, therefore, arbitrary. Whether or not the particular distinctions Haskell makes (where waiting for one second may or may not be an effect depending on how it is implemented) in the form Haskell makes it -- using pure functions and equational reasoning and describing effects with monads -- is actually useful and beneficial is a question for psychologists. Given Haskell's design, monads are certainly useful in Haskell, but that utility can't be generalized to languages with other designs.

[1]: https://en.wikipedia.org/wiki/Computability_theory

Re: Functors, Applicatives, and Monads in Pictures (2013)

#27

Off-topic, but why are Haskell's function signatures written like this? function_name :: Param1Type -> Param2Type -> Param3Type -> ReturnType To me that just makes no sense. There's no way to logically "read" it. The natural way would be "function_name converts a Param1Type into a Param2Type and then ... what?! Is this a chain of functions?" Why not have something sensible like this? function_name :: Param1Type, Para…

because in haskell functions are curried, function_name :: param1 -> param2 -> return is a function that if you only give it param1 it returns a function that takes an argument of param2Type and returns returnType. This way you can easily compose functions

parans make it more obvious:

f :: param1 -> (param2 -> return)

ret = (f p1) p2

Re: Functors, Applicatives, and Monads in Pictures (2013)

#28
post #2

Nice pictures, but I just don't get it. Sure, it's very easy for me to understand monads mathematically, what kind of structure are they. I don't need any pictures for that, the definition suffices for me. But that doesn't tell me what are they good for . We invent things for a reason, and I don't see the reason. Now I know the reason, it's been told to me many times (some way to wrap I/O while preserving functional…

The `Maybe` monad presented here lets you create a language without null references. That's good enough reason for me. Rust doesn't have HKTs like Haskell does, but it still uses the same things that are called monads in Haskell. They just don't want to call them monads.

Re: Functors, Applicatives, and Monads in Pictures (2013)

#29
post #6
post #3

Earlier quoted context omitted.

The reason that the Monad structure is interesting, in my view, is that it's simple and neatly captures the notion of a "computation" that we can compose in different ways. The core useful operator for monads in Haskell is >>=. It has the following type: m a -> (a -> m b) -> m b If you squint, this is like function application with a few extra m's thrown in. Here's normal function application for comparison: a -> (a…

I appreciate your explanation but again it fails to actually show it being useful outside of the context of working around Haskell's strict type system. What the OP and myself would like to see is concrete examples why this is a better approach than the way something would be done without explicitly caring about monads (I say explicitly because I know there is a tendency to say that some given structure is a monad an…

IO, Maybe, ST, STM all being monads gives you the same sort of benefits that you get from Int, Float, Double, Integer, Complex all being numbers.

Re: Functors, Applicatives, and Monads in Pictures (2013)

#30

Off-topic, but why are Haskell's function signatures written like this? function_name :: Param1Type -> Param2Type -> Param3Type -> ReturnType To me that just makes no sense. There's no way to logically "read" it. The natural way would be "function_name converts a Param1Type into a Param2Type and then ... what?! Is this a chain of functions?" Why not have something sensible like this? function_name :: Param1Type, Para…

Two things to add to the other comments: the language is named after Haskell Curry, from whom we get the term "currying," which is what we use to describe "the process of transforming a function that takes multiple arguments into a function that takes just a single argument and returns another function if any arguments are still needed".

Secondly, note that in Haskell a space represents function application -- it's not just there to separate terms.

This stuff might seem crazy, but once you start using it for useful things you come to really miss it in other languages. :)

Post reply on HN