Perl 6 - the future is here, just unevenly distributed

IRC log for #perl6-monads, 2017-01-07

| Channels | #perl6-monads index | Today | | Search | Google Search | Plain-Text | summary

All times shown according to UTC.

Time Nick Message
21:28 ilbot3 joined #perl6-monads
21:28 masak a guy once explained monads to an audience I was in by implementing turtle graphics
21:29 masak welcome!
21:29 perlpilot_ joined #perl6-monads
21:29 masak so, I hear you're interested in monads, yah?
21:29 * moritz nods the bot's head
21:29 masak so, it's Saturday evening and 7 people are talking about monads...
21:30 * perlpilot_ is just intersted in the explanation as he hasn't thought about monads in several years
21:30 masak why turtle graphics? because you move the turtle around, and it has a bunch of state that you can change, OK?
21:30 perlpilot_ (I've forgotten whatever I knew I'm sure)
21:30 masak state is a known-sore point in functional languages
21:31 masak state is super-easy on a Turing machine model
21:31 masak because the Turing machine is a mechanical thing with lots of moving parts
21:31 masak functional programming (lambda calculus and its decendants) doesn't really have moving parts, just term rewriting
21:31 masak anyway
21:32 Topic for #perl6-monads is now http://irclog.perlgeek.de/perl6-monads
21:32 masak a monad is a turtle -- is everyone clear on this so far?
21:32 masak any questions?
21:33 moritz they taste the same too?
21:33 perlpilot_ monad soup?
21:33 masak taste the same, but monads are slightly chewier
21:34 * masak has eaten turtle, once, in .cn
21:34 masak anyway, back to the guy with the turtle graphics
21:34 masak he was implementing all the normal things: move the turtle forwards, turn it this way and that, pen up, pen down
21:35 masak you can imagine how all of those change some internal state, and possibly also add graphic primitives to a canvas somewhere
21:35 masak then he went on to draw things
21:36 masak like a fractal tree like this: https://commons.wikimedia.org/wiki/File:Fractal_plant.jpg
21:36 masak now, it turns out
21:36 masak when you want to draw something like that, you suddenly want to "save" and "load" the turtle's whole state, like in a computer game
21:37 masak in order to "teleport" it back to some position so you don't have to painstakingly retrace your steps
21:37 moritz or clone it when it's at the save point
21:38 moritz and only move one copy in the first place
21:38 perlpilot bifurcated turtle
21:38 masak sure, but FP doesn't think in terms of modifying a turtle object
21:39 masak every "modification" in something like Haskell is conceptually a whole new copy
21:40 masak here's someone trying to do turtle graphics with a monad: http://stackoverflow.com/questions/13331336/turtle-graphics-as-a-haskell-monad#13333325
21:40 masak (though not the guy who was giving that talk)
21:41 masak anyway, let's back away from the specifics of turtles and look at the *type* of itch we're trying to scratch
21:42 notviki left #perl6-monads
21:43 masak (a) we want to talk about sequences of actions
21:43 rafaschp joined #perl6-monads
21:43 masak (b) a sequence of actions are carried out in the order written, and together compose to an action
21:47 masak in the case of the turtle and the state monad, we are also interested in those "load" and "save" operations -- but that's specific to the state monad and not something monads in general do
21:47 masak anyway
21:48 rafaschp What's the difference between a monad and a program?
21:48 masak FP uses functions a lot. when all you have is a hammer^Wfunction, you tend to start to think in a certain way
21:48 masak rafaschp: a good question!
21:48 masak rafaschp: I get the feeling that in Haskell at least, the type of the program is `IO ()` -- a monad
21:48 masak or the type of `main` or whatever
21:49 masak why? because the only way you have side effects in Haskell is through monads, and the program itself most certainly does have side effects
21:49 hartenfels Using that hammer, solving sequences of actions seems to involve passing and returning the turtle to and from each function, because that's the only way you'll get a different result from them.
21:51 rafaschp So, a monad is like a programable state machine?
21:52 * moritz doesn't think masak has gotten to the point what a monad actually is
21:52 masak hartenfels: yes
21:52 masak rafaschp: hm -- not sure how well that analogy holds up
21:52 masak sorry, I lost the connection there for a while
21:53 rafaschp I'm listening.
21:53 rafaschp I asked the question because you were disconnected, sorry.
21:53 masak even though Haskell programs are of type `IO ()`, I also get the feeling that you try to write most of the program "outside of the monad", because pure FP code is nicer
21:54 rafaschp Pure FP code is nicer for some definition of nicer.
21:54 masak anyway, FP is most certainly equipped to handle *sequencing*, which is what most of this is about
21:54 masak how do you implement sequencing in lambda calculus? you basically just pass something to a function, and let the argument evaluation logic provide the sequence points
21:55 masak so it does work, to get turtle-graphics-like sequencing from an FP program
21:55 masak but it doesn't look so nice :)
21:55 masak look at the `add` example at https://en.wikipedia.org/wiki/Monad_(functional_programming)#The_Maybe_monad and you see what I mean
21:55 masak people talk about "pyramid of doom" in the JavaScript world when doing callbacks in callbacks several nested levels deep
21:55 masak same thing would happen here
21:56 masak and then look at the code under "Using some additional syntactic sugar known as do-notation, the example can be written as:"
21:56 masak that's what monadic logic gives you
21:57 masak but it's quite important -- and pretty impressive -- that the `do` notation in Haskell is actually syntactic sugar for the code right *above* that sentence
21:57 masak yes, there you see the raw lambdas being passed around. those lambdas are the ones that make the sequencing happen
21:57 moritz that makes a scary amount of sense
21:58 masak :)
21:58 masak linger on this for a moment, though
21:58 rafaschp I see, "nomads" is a fancy name for people that like to say FP is way better to do imperative programming without having to admit to it. xD
21:58 masak in Haskell, `do` notation (that is, all imperative programming) is *syntactic sugar* for lambdas being passed around to produce sequencing
21:58 masak rafaschp: correct
21:58 geekosaur there's an impressive amount of takeup of haskell as javascript generator (or a haskell-like language generating javascript) precisely because you can use do notation to describe all the callbacks as if you were programming imperatively
21:59 moritz so there are two lambdas that extract the values from the Maybe monad, so that you can focus on the base case
21:59 masak rafaschp: I mean, if someone claimed that they had reduced imperative programming to something more fundamental, at least I would perk up a bit and listen
22:00 masak moritz: yeah. in the Maybe monad, only the `Just` case is actually interesting. the `Nothing` case usually means you just don't consider it, and execution stops/backtracks
22:00 rafaschp I don't see FP as a "more fundamental" way, just as an equivalent way. The processors are imperative.
22:00 hartenfels The reason behind the `return` is just to make the type system happy?
22:00 rafaschp The fact that it can be translated automatically is very cool, though.
22:00 geekosaur it turns "value" into "callback producing value"
22:00 masak hartenfels: you should read `return` here as "here, take this normal value and produce a monad from it that wraps that value"
22:01 geekosaur sometimes you could infer this in a language with a looser type system, but sometimes you can't (and in Haskell, such inference never happens)
22:01 hartenfels Yeah, I get that. But it's not like I actually care about the monad at that point, I just want the value.
22:01 hartenfels But it makes sense, since I might also get Nothing.
22:01 hartenfels In this case.
22:01 masak moritz: even cooler: the exact same `do` notation works for (e.g.) the List monad, and what's implicit there is `flatmap` instead of the Nothing/Just distinction
22:01 masak moritz: and so on for every monad
22:03 masak hartenfels: once you're in a monad, you can't get a raw value out of it, ever
22:03 masak see https://xkcd.com/248/
22:03 hartenfels Can't I case over it in the function that calls it?
22:03 hartenfels Or whatever Haskell calls it
22:04 hartenfels Pattern match over it.
22:04 masak nope
22:04 moritz yes, but the function in which you do it still has to return a monad
22:04 masak hartenfels: perhaps easiest to understand with the `IO` monad
22:04 hartenfels Oh, I think I'm misunderstanding “in a monad”
22:04 masak once something starts to have side effects, you can't just wash it and make it pure again
22:05 masak everything that touches something with a monad similarly becomes "tainted"
22:05 masak it's like a pirate curse
22:05 hartenfels I mean once I am done with doing the sequence stuff, I can pattern match over the resulting monad and get the value out if it produced one.
22:05 masak only *inside the monad*
22:06 masak case in point: once you get a value back from a Promise, you can only relate to that value inside of the .then callback
22:06 moritz masak: so how does reduce work? it takes a monad (list) as an input, and produces a single value, no?
22:06 moritz s/reduce/fold/
22:07 masak moritz: monad is a type class/interface/role here -- if you can get the value back out you can be sure it wasn't thanks to the monad typeclass :)
22:08 moritz masak: ah, so a list is more than just a monad, and the more-than part allows things like fold or head
22:09 hartenfels Something like `Maybe Int -> Int f; f Nothing = 0; f Just a = a` would let me get the value out of the Maybe monad, but not because of its monadyness?
22:09 rafaschp "type" is a way for the "FP is superior" people to likewise do OOP without adminting it?
22:09 geekosaur hartenfels, the monad interface itself doesn't give you a way to get anuything out. *particular* monads may
22:09 masak moritz: aye
22:10 hartenfels Ah okay, so getting stuff out is not a thing that a monad does on its own.
22:10 geekosaur rafaschp, not really, depending on what you mean by OOP. OOP is generally understood to be subtyping; monads don't help you with that, nor do Haskell typeclasses (and if you try to abuse typeclasses as OOP, you quickly run into the difference between Hindley-Milner typing and subtyping)
22:11 rafaschp Ok, thanks.
22:11 geekosaur you could say subtyping runs "backwards" from most FP type systems
22:11 rafaschp I was thinking about other things I knew about types, then.
22:11 masak hartenfels: I think you just implemented fromJust :)
22:12 masak hartenfels: see https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html#v%3AfromJust
22:12 geekosaur instead of, say, Num giving you access to anything that any Num instance could do, it gives you access only to the things that *all* of them can do.
22:12 masak yeah, that's a good way to phrase it
22:12 geekosaur (which is, more or less, the difference between subtyping and Hindley-Milner, respectively)
22:12 masak it feels a bit inside-out
22:13 geekosaur subtyping is union, H-M is intersection
22:13 geekosaur or, equivalently, "or" vs. "and"
22:13 masak duals, they strike again!
22:13 masak anyway
22:14 masak we haven't really pinned down what monads are yet, have we?
22:14 geekosaur nope :)
22:14 masak but we've seen several examples: State, IO, Maybe, List...
22:14 geekosaur well, sort of operationally
22:14 masak and they all look quite different
22:14 geekosaur but then, by some arguments that's all that matters
22:14 masak some of them (like Maybe and List) focus on data structures
22:15 geekosaur not like you have to know category theory to *use* them effectively
22:15 masak some of them (like State and IO) focus on sequencing and side effects
22:15 masak these are two aspects of monads, and they're somewhat at odds
22:15 masak in the sense that they are two competing mental models
22:15 masak kind of like particle vs wave, I guess
22:16 masak so let's find a uniting common ground
22:16 masak a monad is just this:
22:16 masak (ready?)
22:16 masak it's something with a `return` and with a `bind`
22:16 masak and those have to live up to some pretty basic rules
22:16 masak that's all
22:17 masak all the examples you've seen above define their `return` and their `bind` in some way, and that's what makes them monads
22:17 masak all the monad tutorials out there should just say this and be done with it
22:17 moritz so, how doe IO and List return and bind?
22:17 moritz s/doe/do/
22:17 masak good, let's talk about that
22:17 masak List first, because I know it quite well :)
22:18 masak `return 42` should put 42 in the List monad
22:18 masak so the result is... `[42]`. done
22:20 masak `bind xs f` is implemented as `flatmap`
22:20 masak much like Perl 5's `map`
22:21 masak so if xs is `[1, 2, 3]` and `f` is `\n -> [n, n * 2]`, then `bind xs f` gives you `[1, 2, 2, 4, 3, 6]`
22:22 masak written as Perl 5: `map { $_, $_ * 2 } 1, 2, 3` gives you `1, 2, 2, 4, 3, 6`
22:22 masak note the cute symmetry here:
22:22 masak `return` knows how to turn *zero* layers of monad to *one* layer of monad
22:23 masak meanwhile, `bind` says "but what if you have *two* layers of monad; I only wanted one!"
22:23 masak and then solves that for you
22:23 rafaschp It's jast a lame function, then.
22:23 masak that's why it's `flatmap`, and that's why you don't get `[[1, 2], [2, 4], [3, 6]]`
22:24 masak rafaschp: but then again, what isn't?
22:25 rafaschp They should generalize their models.
22:25 geekosaur that's ... what monad is about
22:25 moritz so next time somebody asks me what monads are, I say "just a bunch of functions, d'oh" :-)
22:26 geekosaur pretty much
22:27 masak moritz: I think I can even get you to grok http://stackoverflow.com/questions/3870088/a-monad-is-just-a-monoid-in-the-category-of-endofunctors-whats-the-proble%E2%85%BF -- it's pretty straightforward :)
22:27 geekosaur there's an ongoing joke in the haskell community about monad tutorials that all miss the point ("burrito" is a reference to a joke monad tutorial that mocks the whole class of monad tutorials)
22:27 rafaschp If they want functions in their language, they should add that. And stop pretending it's some mathematical holy grail because it's missing features.
22:27 masak geekosaur: the "burrito" monad tutorial was written by mjd
22:27 masak geekosaur: and what makes you think he was joking? :)
22:27 geekosaur maybe there's two of them then. I'm thinking of one done by Don Stewart
22:27 masak ah.
22:28 geekosaur two of them, the burrito and the spacesuit
22:28 masak http://blog.plover.com/prog/burritos.html
22:28 geekosaur the burrito caught on
22:28 geekosaur possibly because of mjd's
22:29 masak there's a bit of survivor's bias in monad tutorials, I guess
22:29 masak something makes it click for a certain person
22:30 masak and they write that part up, convinced it will help lots of others
22:30 rafaschp It could all be so simple.
22:30 masak well, monads *are* simple -- in about the same way Git is
22:30 geekosaur except most such tutorials you can point to a particular monad and ask how that fits in, and the answer is "it doesn't"
22:30 masak the problem is clearing away all the mental baggage that obstructs the simplicity
22:31 hartenfels Presumably what makes monads nice is having the syntax sugar to deal with them?
22:31 masak geekosaur: well, the above-mentioned container/sequencing split doesn't help, of course
22:31 masak hartenfels: oh, that's certainly a big deal, yes
22:31 geekosaur most monad tutorials I've seen miss the point in some way --- granted I stopped looking  after awhile
22:31 moritz masak: why does that stackoverflow post use "join" instead of "bind"?
22:31 masak hartenfels: but it goes beyond that -- the underlying semantic framework is simply very general
22:31 geekosaur ...hoo boy...
22:31 masak hartenfels: in the same way as saying "it's a visitor pattern", you can say "it's a monad", and it means something useful
22:32 masak moritz: there are several possible fundamental operators
22:32 moritz masak: ok
22:32 masak moritz: I think `bind` is Haskell's favorite. `join` is more towards CT... I think...
22:32 geekosaur yes and no
22:32 masak it all comes out the same. you can define one in terms of the other, that's the important bit
22:33 geekosaur think of it this way: for a list, you can break "bind" down into two operations, map and concat
22:33 geekosaur "join" is the generalized term for the concat operation
22:34 masak ah, geekosaur++
22:34 geekosaur it's most clearly visible for lists, where map = map and join = concat, but the same breakdown can be done for any monad
22:34 hartenfels I will now start calling it the monad pattern then.
22:34 masak I'm used to thinking about it in terms of functor, η and μ :P
22:35 masak hartenfels: again, as above, the hardcore thing to say is "a monad is just a monoid in the category of endomorphisms, what's the big deal?"
22:36 geekosaur and the usual category theory representation is based on that breakdown. but for Haskell, bind is a more useful general operation because it gives a simple translation from do notation to callback expressions
22:36 rafaschp I like "a monad is a lame function" better, because people that like monads are usually hang-up on the (equally meaningless) definition mathematians use for "funtion".
22:37 * moritz has to sleep soon, but will backlog
22:37 geekosaur (and then Haskell reconstructs join from bind, because join is just bind-ing the identity function
22:37 hartenfels Well, I want it to be less hardcore. Calling them monads always makes them seem like things and not just bits of code that work a certain way.
22:37 masak hartenfels: it is a pattern, for sure
22:37 masak or rather, a typeclass
22:38 masak hartenfels: but I think you're onto something. what you should translate "it's just a monad" to in your head is something akin to "it gives a certain set of well-known guarantees"
22:38 hartenfels Pretty much.
22:38 masak the specifics of which are important of course, but also easy to learn
22:39 geekosaur one of the confusions here is that many things which have to be treated as design patterns in other languages can be captured as libraries in Haskell, so we don't tend to think in terms of Monad as design pattern
22:39 masak for me, thinking of `return` as "turning a muggle value into a monad value" and `bind` as "combining two monad values into one monad value" helps a lot
22:39 geekosaur but when viewed from the standpoint of other languages, that's exactly what it is
22:39 masak aye
22:40 masak again, in Haskell/FP, some things are a bit inside-out
22:41 hartenfels Somehow calling them “monads” made it sound like they were god-given entities like functions or record values, rather than just codified common behavior.
22:42 geekosaur (there is a certain dismissive attitude in the Haskell community that a "design pattern" indicates a shortcoming in a language being worked around. which isn't really true (usually; mostly that's a barb aimed at Java) and means many Haskellers won't admit that something is a design pattern when it actually is)
22:42 masak geekosaur: oh! good to know.
22:42 masak geekosaur: I know mjd has said something similar, that design patterns are weaknesses in the underlying language
22:43 moritz one could say something similar about Haskell
22:43 masak hartenfels: right -- calling it a monad means we recognize some *part* of its behavior as being similar to many other things
22:43 moritz the fact that you need monads to do IO is a weakness, because monads are hard to understand
22:43 masak I don't know that they are, though
22:43 rafaschp Then instead of describing the thing directly, they try and make up a mathematical model for it? To pretend something is more than it really is?
22:43 hartenfels Maybe I'll even call it an interface design pattern to make the Java analogy even worse :P
22:44 masak I mean, you can explain Go to someone in a very inefficient/confusing way
22:44 masak doesn't mean that Go is difficult to understand
22:44 hartenfels But great explanation masak++
22:44 geekosaur masak, sometimes it is true. and sometimes a design pattern is nothing more than an API.
22:44 masak rafaschp: monads are older than Haskell :)
22:44 masak *nod*
22:45 masak and, on that note...
22:45 rafaschp Lispers are the same way?
22:45 masak ...thanks for coming. try the veal.
22:45 rafaschp left #perl6-monads
22:45 hartenfels Thanks for explaining.
22:46 masak pleasure. I learned some things, too.
22:46 geekosaur and often it's something in between --- becuase, no matter how flexible the languge, the real world is more flexible yet
22:55 geekosaur left #perl6-monads
23:24 geekosaur joined #perl6-monads

| Channels | #perl6-monads index | Today | | Search | Google Search | Plain-Text | summary