Live data from Hacker News

Functors, Applicatives, and Monads in Pictures (2013)

adit.io

41–50 of 56 posts

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

#41
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.

The order of operations here is "right associative". So

  A -> B -> C -> D
is equivalent to any of the following

  A -> (B -> C -> D)
  A -> (B -> (C -> D))
  A -> B -> (C -> D)
They're equivalent through currying. But you can only add or remove parentheses for stuff that is on the right of a function arrow. (A -> B) -> (C -> D) is a different thing.

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

#42
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…

https://news.ycombinator.com/item?id=10271527

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

#43

Earlier quoted context omitted.

You kind of just have to use them to “get it”, but here’s an analogy: if you write a data structure, you naturally want to make it “iterable” in your language’s usual way, so you can take advantage of a library of generic functions for working with iterable things. Same goes for monads. If we have N data types and M functions, instead of writing N×M implementations, we can write just N monad instances + M generic imp…

> Same goes for monads. If we have N data types and M functions, instead of writing N×M implementations, we can write just N monad instances + M generic implementations. Bear with me for a bit, because I still don't get it (although I'm not the OP, I share the same doubts). In OO terms, if you have N types and M functions, with M different behaviours (function code), you aggregate the N types into an inheritance tree…

In OO terms, I’m talking about having N classes—which for the sake of argument are not related by inheritance—one interface, and M functions implemented in terms of that interface. Clearly it’s cheaper to implement the interface once for each class than to implement each function for each class.

That part has nothing to do with monads. The advantage of monads is the actual functionality they provide, of first-class effects and easy EDSL creation.

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

#44

Earlier quoted context omitted.

You kind of just have to use them to “get it”, but here’s an analogy: if you write a data structure, you naturally want to make it “iterable” in your language’s usual way, so you can take advantage of a library of generic functions for working with iterable things. Same goes for monads. If we have N data types and M functions, instead of writing N×M implementations, we can write just N monad instances + M generic imp…

> Same goes for monads. If we have N data types and M functions, instead of writing N×M implementations, we can write just N monad instances + M generic implementations. Bear with me for a bit, because I still don't get it (although I'm not the OP, I share the same doubts). In OO terms, if you have N types and M functions, with M different behaviours (function code), you aggregate the N types into an inheritance tree…

> In OO terms, if you have N types and M functions, with M different behaviours (function code), you aggregate the N types into an inheritance tree that makes you write 1xM functions (one function against the ancestor of the N types).

In general, its O(M+N), because you write the M methods in the ancestor that you talk about, and then O(N) class-specific implementations of the underlying functionality on which the M methods rely.

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

#45

Earlier quoted context omitted.

You kind of just have to use them to “get it”, but here’s an analogy: if you write a data structure, you naturally want to make it “iterable” in your language’s usual way, so you can take advantage of a library of generic functions for working with iterable things. Same goes for monads. If we have N data types and M functions, instead of writing N×M implementations, we can write just N monad instances + M generic imp…

> Same goes for monads. If we have N data types and M functions, instead of writing N×M implementations, we can write just N monad instances + M generic implementations. Bear with me for a bit, because I still don't get it (although I'm not the OP, I share the same doubts). In OO terms, if you have N types and M functions, with M different behaviours (function code), you aggregate the N types into an inheritance tree…

You could implement monad as a class that List, Either, Writer and all the rest extended. There are practical issues: you need higher-kinded types to be able to write the monad interface, which not many OO languages have (Scala is the only one I can think of), and writing the functions as instance methods would require "F-bounded polymorphism" which is tricky ( http://logji.blogspot.co.uk/2012/11/f-bounded-type-polymorph... - that link even has an example of how you'd write Monadic as an interface you extend rather than a typeclass (don't be intimidated by the type lambda, it's a scala wart), although it doesn't compile in scala as implemented today), and you also need a way to associate the "zero" with the type in general rather than a particular instance of it (i.e. you need a static virtual method - I think maybe C# supports them?) but in principle there's no reason you couldn't do it.

(There are arguments that type classes are a more expressive way to solve these kind of N*M problems than inheritance - see https://en.wikipedia.org/wiki/Expression_problem - but that's orthogonal really)

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

#46
post #6

Earlier quoted context omitted.

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…

I'll take a shot at it. Quoting tikhoni: > For Maybe, being a monad gives us a standard way of working with values while automatically dealing with Nothing. It abstracts over repetitive null checking and lets us easily build up Maybe values based on other Maybe values. To expand on that a bit, in a way that might work for you (or might not): I've got a function f a that exists. It works. It does exactly what I want.…

Isn't Maybe being an instance of Applicative enough in this case?

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

#47
post #46

Earlier quoted context omitted.

I'll take a shot at it. Quoting tikhoni: > For Maybe, being a monad gives us a standard way of working with values while automatically dealing with Nothing. It abstracts over repetitive null checking and lets us easily build up Maybe values based on other Maybe values. To expand on that a bit, in a way that might work for you (or might not): I've got a function f a that exists. It works. It does exactly what I want.…

Isn't Maybe being an instance of Applicative enough in this case?

Maybe...

But seriously, I guess I think it's not a Monad. The Monad signature (in this case) is

  (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
and I think what we really want (and what I said we wanted to do) is

  Maybe a -> (a -> b) -> Maybe b
I don't know whether that's Applicative or Functor, but I don't think it's Monad.

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

#48
post #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.

[deleted]

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

#49
post #48
post #28

Earlier quoted context omitted.

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.

[deleted]

Phrased another way, in any language, Monads work as a design pattern, and Rust had built-in implementations of that pattern; but some languages (Haskell, etc.) support Monads as a construct against which you can program directly, which is a more powerful abstraction than spring or implementing it as a design pattern.

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

#50
post #14
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…

Whoever told you it has to do with IO and functional purity vastly oversimplified things. That is just one use case. Monads take care of a very common computation pattern: wrapping and unwrapping data from a container to do stuff with it. This process is error-prone and leads to code bloat if done by hand whenever needed. I mean, how often have you had to apply a function to every element in a vector of values? fmap…

> Monads take care of a very common computation pattern: wrapping and unwrapping data from a container to do stuff with it.

Isn't this what Functor does with `fmap`, not Monad?

Even if Monad did not exist and you only had Functor and Applicative, you'd be able to compose `pure` and `fmap` to get the same effect as bind, right?

Post reply on HN