Here's a story: 1 I started this video on monads 2 he mentioned functors and said "watch this video if you don't know about functors" 3 I paused the video and opened funtors in a new tab 4 in the functors video he said "if you don't know about maps, watch this video about it" 5 i paused functors and opened the maps video in a new tab. okay now hold it......... did you notice something? My time on youtube has turned into a subroutine mechanism....... I find this fascinating :D
So what you're saying is that this video is a Monad, because it flatMaps the recursive promise of previous videos into a final distilled answer to the question of what a Monad is... That's meta.
I really mean it. I think that if Gang of Four existed at the same time as Haskell, they would have described it just like you did. Obviously there is more, but your laid out the fundamental concepts in a very straightforward, intuitive way.
This is the only video that sets fire on our monad appetite for more knowledge. One of the (several) main qualities of funfunfunction videos: passion, appetite, fun. Dr. Boolean's would be a great next step, if I may say.
Not only the best monad tutorial that I have ever seen but the best flatMap example that I also have ever seen: from a very complex term called 'Monad' to 'As simple as that'. Cheers for it! I was sick of reading about monads and Haskel.
oh man, I'm so happy I found you and DevTips, you guys are taking youtube tutorials to a new level, making it super entertaining even serious and advanced subjects like this. You really seem to give way more importance to the learning experience than to the "look-how-good-I-am-at-this-I-learned-it-from-boring-docs-and-you-dont-deserve-to-learn-it-in-a-less-boring-way" kind of feeling Looking forward to see you here in Brazil!
I like how concise and distilled the explanation of monads was delivered yet was still chocked full of sweet streaming and promises morsels. Well done mate.
Probably because it's being run through an API call before logging out the response, so the order is going to be random based on whichever API response arrives first.
Don't ever stop making videos. You have the best js series, by far! Everything is well put together, informative, and entertaining. I have been a professional coder for 17 years, and still find lots of value in your videos. I even made my wife watch your episode on "Too many frameworks", just for the cookies comment. haha
Thanks for the explanation linking monads, 'bind', 'chain', and 'then'. That definitely helps tons. One question. Since 'then' has flatMapped the promise response into JSON in line 15 (around 8:42), would we be able to use 'map' instead of 'then' in line 16, and get the same result? const promise = fetch(url) .then(response =>respons.json()) .map(parsedResponse => ....
+Dan Williams Not out of the box, because Promises don't implement a literal .map method. However, .then will work exactly AS map as long as you're careful about what type of value you return (as long as it isn't a Promise: i.e. as long as it isn't something that implements then, basically). You could Promise.prototype.map = Promise.prototype.then, of course, but... don't. Probably just remember that .then is overloaded. Just for fun, do implement .ap though! Promise.prototype.ap = function(p){ return p.then(x => this.then(fn => fn(x)) ); } var addTwo = curry((x,y)=>x+y); var delay = (v,n) => new Promise(r=> setTimeout(_=>r(v), n)); Promise.resolve(addTwo) .ap(delay(4,1000)) .ap(delay(6,3000)) .then(x=>console.log(x));//-> after both delays complete, the values are added and returned!
+Drew Tipson Interesting insight Drew! Then since Promises don't technically implement map, are they still functors? Are all monads functors by default? Is flatMap enough to justify the title?
+Dan Williams I would argue that they are still Functors, but here, particular to Javascript, we have a distinction between the implementation vs. the theory. I'd argue that just because the method name of something isn't literally the string key "map" doesn't mean that something isn't a Functor: it implements the Functor interface map, and it passes the Functor laws, so it's a Functor, end of story, in my book! I mean, if you wrote an entire language language that used non-English words, .map wouldn't be Functor["map"] it'd be, say, Functor["mapa"]. But it'd still be a Functor. However, there's the issue of coordination to consider in javascript. In higher-order operations, we'd like to be able to pass a Functor, ANY functor off into a function, and know that we can use a map operation on it just by calling Functor.map(f). If it's not literally available at ["map"] though, that coordination won't work! We run into this naming problem all the time both when extending the spec (ES7's "Array.includes" should have been called "Array.contains" but couldn't be, for instance, because that method name was being baked into the Array prototype all over the web with a different type signature/behavior) and developing pointfree wrappers for all Functor and Monad types: should we call flatMap bind? Nope, we can't do that, since that already exists and does something totally different. .flatMap? .chain? Maybe, but all those decisions have consequences for, again, larger-scale coordination. Most of the functional JS world seems to have settled on calling bind "chain." But ES(8?) may include native .flatMap and .flatten methods on Arrays, which means that yet again, we could be headed for having the same things used with different names. So to the question of whether all Monads are Functors: yes they definitely are! That's because once you have a .flatMap that passes all the Monad laws, you can derive .map "for free" by composing the pointed function (Monad.of) with the mapping function and just passing that to flatMap/chain. But again, we hit the possibility that, in Javascript, it's certainly _possible_ to define a legit Monad but not actually _expose_ a Functor implementation, even though it'd be trivial to do so! And Promises are exactly such a case: not only is a .map implementation possible, it's actually implemented. But it's called .then (which is ALSO flatMap!) instead. So in some pointfree wrappers, you might even see things like const map = curry((f, xs) => xs[xs.map?"map":"then"](f) ); which will try to use map if available, but then to handle the Promise case, fall back to trying then instead. As I understand it, in a language like Haskell, you don't run into this problem because the type system builds these packages onto each other directly: once you've defined a Monad you by default have a map interface for it out of the box. But with javascript, it's all loosey-goosey: you can define whatever methods you want on anything, and there's no type system to enforce proper behavior. You could easily define a method on something called map that doesn't obey the functor laws and nobody can stop you.
I wonder how interop could be achieved? I mean I would have to cast everything to bacon streams if I want to use bacon's flatMap implementation right? Just like I have to cast everything into a Promise if using `then`. I doubt there is a better way, right?
Just watched whole functional programming series in like 3 hours after I found out this channel. I'm feeling like understanding at least 90% of it, and thats because most of it was really, really similar to Java8 streams and lambda expressions. And of course because episodes are really, really cool!
Ok, I went through your Functional Programming series and you asked for it, so I'll give it to you. I'm interested in Functional Programming because I want to learn how to make small simple bits of code and re-use it all over the place without making a Moebius surface out of my code. So my current constraints are: I'm programming in IBM's RPGLE, procedural, strongly typed, compiled language and my employer restricts the use of procedures (an equivalent of a function, he has his reasons). He is going to open the door to DB2 SQL procedures and here is where I want to create useful, re-usable, beautiful functions that will be used all over the place. My worry is creating functions that aren't composable and ending up with one big useless library that won't be re-usable, ending up with tons of copies of each procedure, for every new scenario. I want to ask you to give me pointers on how to think, the rules of thumb, good practices, how you keep data and functions separated and where do they connect. I know this is a tall order, but you do like recipes xD Thanks for the rest of the videos, I feel they gave me some insight into this question, but I feel I still need more. Keep up the good work ;)
Thanks, defiantly the best beginner introduction to monads that I have seen that is not cursed with the "curse of the monad" ("curse of the monad": once you understand what a monad is, you lose the ability to teach or explain what a monad is)
.then implements map and flatMap in one. I’m playing a little fast and loose with the definition and many would say it’s not strictly a monad, but I think that’s being correct to the point of uselessness - in practice, it’s a monad.
So we can say that , flatMap is general to Promises, but when we talk about Map .then(result => Promise.resolve(result.item)) would enact the map part of a monad
Hmm, your statement does not make sense for me, sorry. .then will do the job of both map and flatMap without modification: .then(result => result.item) //map, expects callback to return non-monadic value .then(result => downloadImage(result.item.avatarUrl)) //flatMap, expects callback to return monad, which flatMap will unwrap
Dude, explaining monads always sound 100% confusingly terrifying for me, now it's just 98%. BUT YOU DID A GREAT JOB, now I can start explaining what is a monad. And a functor. GOOD!
I come from a Python background so the native async processing in js confuses me sometimes. But how can I make sure that the values in the stream are processed in the order they were pushed without having to wait for each value to resolve?
Eduardo Tenorio Well asyncio is included in the standard interpreter for python but is not as depending as JS. And it might actually be both since lists are not promises and therefore not interfere with Pythons definition.
I guess you could use "Promise.all" and get in return an array of results in the order you provided them to the ".all" method. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
It would simply return the unresolved promises. flatMap will not flatten ANY monad, only monad of the same type. flatMap on a stream will only flatten streams, just like .then on a promise will only flatten promises.
You definitely make programming concepts easier and more fun. Your videos are changing the way I think about programming so I'll make sure to thank you in person when you come to Brazil!
I find a graphical representation of streams within streams, and the flattening of these makes people get it faster. also relating it to arrays and concat + map
thanks for this video and the other two about Functors. This was what I was looking for, a pratical and applied programming point of view about Monads, not just another complex mathematical definition. This helped a lot. Thanks!
Great explanation. I think if I'd watched this before trying to learn monads from other sources, they would have made a lot more sense earlier on. It's so helpful to have a simple idea to fall back on when learning something (I.e. at least I know "this" about it). Kinda like a set of coat hooks to hang all the details on. I think that's the "get monads" idea you were talking about.
It is easy to learn something when you actually need it. It's like reinventing the wheel because you didn't care what a wheel is and never needed one. Then you make the wheel and share your findings, but everyone else says it was already invented and they tried to tell you that... Monads, monoids, semigroups and many other math concepts are just that. If you try to write a program that does symbolic computations you'll probably learn all these concepts on the way and they will be quite natural and useful. I like haskell because it uses correct names for most things and many design choices are really good. I like the modules exporting things and when you import something you can specify what exactly you want to import. Another cool thing is "qualified" keyword. Instead of putting everything in a library in a namespace(as you would do in C++) you specify the namespace when you import it!
Is there an example of an useful functor that couldn't be implemented as a monad? Instead of simply deliberately removing the chain/flatmap from a monad?
How can I use these super powers in the enterprise world? Like maybe even in server-side code too? (I do full stack .NET code with C#/typescript (with Knockout to bind our viewModels)). I like these ideas and want to use them! We kind of use some of them in our typescript code, and we use bluebird for promises (so we use then callbacks and all that jazz), but I feel like I don't use these things in everyday code (except with our super nice postJsonPromise), but maybe using promises and stuff is the answer (I don't think I can use F# :c).
Is there a standard for which property is returned for each item when calling flatMap? Eg would it always be "value": { value: "this would be returned", otherValue: "this wouldn't" }
There is very strict rules for it in Haskell (it's what people refer to with the monad laws) but seen across all languages it is really just whatever value is contained within the monad. Think of it conceptually rather than the name of a property on an object or something. The monad, a stream or a promise or or some other, is a kind of box that contain a value or values, and mapping it is a way of getting to those values, and flatMapping is a way of combining those values with other monads of the same type. Sort of. ;) this is something that you just have to do a bit in different ways until you find an explanation that works for you personally.
This was interesting. I think the follow up video should showcase more practical examples of useful applications of monads. As often, the most important is not only to understand how a tool works, but to build an intuition on when it's appropriate to use it.
Monads are a higher transformation of an object or entity, through functions, were we can do extra computation. In this video that "extra computation" is the "flat"
I think I understand the functions your using, map and flatMap, and .then. So a monad is a functor that takes an unresolved structure, like a stream or promise, and allows it to resolve before subsequent instructions can proceed. Do I have that right?
+James MacIvor, not strictly right because monads aren't necessarily async but good approach. Monads are for composing functionalities depending of a run time value. One way of understanding monads is separating promise then() in three functionalities. map() is for transforming the values inside the promise (only if it is resolved), for example toUppercase. flatMap() (or chain()) is for composing promises, for example fetch a value from a server and based on that run time value make another fetch. Finally then() is when all chained promises are resolved, make something with that value. Take a look to folktale Task or ramda Future, they have a clean separation of three functionalities.
+Anastasi Bakolias I'd say: implements .flatMap() AS .then(), rather than instead of. One more thing being a monad gets you is the ability to define an applicative method (and thus if the monad contains a unary function or a curried function instead of a value, you can pass it its values each also wrapped in Monadic context and then get a Monad of the same type out containing the result)
After watching #10 an #11.... yeah, that made sense... Interesting (or not, maybe just silly) question: Why did the words order change when you added the map with the toUpperCase()?
It's just a PNG + Uberlayer. I've tested every single layout app and none of them gives the pixel-perfection that I need for the videos. You can check the gear + behind the scenes videos for more info.
+funfunfunction Sure. Before applying flatmap we see that Bacon.fromPromise({}) is returned. Instead of empty brackets I expected to see Bacon.fromPromise({cat}), ie the unflattened stream. This obviously isn't the case and i was wondering why. Thanks for the reply
+Themis Papavasileiou the thing is, before flattening the stream, we don't know what is in it. There is no way map could do what you ask, because the cat has not "arrived" yet. There is nothing in the stream at that point in time. flatMap will understand that the return value is a stream, and wait for stream to end, but map will not have that extra cleverness, and return it immideately, before there is something "in" the stream.
Can someone clear this up for me? I don't understand how methods like map and flatMap work can work for streams. Do they wait until the stream is finished receiving all data before it moves on to the next method? For example, stream.flatMap().map(toUppercase); ? What if the stream receives more data as it is in the process of performing flatMap and map? Thanks!
The stream processes as it goes. If you watch closely, you can see that the values are not coming out in the same order as they come in, which is because the network requests are coming in at different times. Some stream operations cannot be performed until the stream has ended, like say, a sort, or toArray, but the operation in the example can be performed as the items come in.
Could you tell me why do I need them if promises give me all everything I need? I see lots of info about streams, how to use them, but I don't see WHY.. If I need to do http request I just use promise, WHY do I want to do stream......?
Promises can only produce one value. A stream can produce any number of values. A stream can do everything a promise can do, but the reverse is not true.
This is the seventh explanation of monads I'm seeing and the only one which makes sense. In fact it seems so easy and so unrelated to previous ones that I'm kinda suspicious that it's not actually about monads.
I have been watching your videos and this is the best. why? Using portuguese words you show us wich you know the brazilian desire to learn js! But we, brazilians, has two challenges: learn english and after learn JS! Thx by your videos and your wonderful english, i'm learning coding and languages!
For all you JavaScript or Python Twisted programmers who do async code using callbacks/promises/futures, "then" is monadic bind is flatMap! In Haskell you use then aka >>= for both synchronous code (IO,State) and async code that way you "transform" your async code to be synchronous code to and back again, and add "semantics". Basically Monads allow you to abstract away the semantics of your "sequential" code allowing it to evolve independently from your code itself. - EDITED - lol then is right there and I didn't even notice that. The types are very similar for flatMap / >>= and then m a -> (a -> m b) -> m b, where m = Promise instead of IO, List, Maybe, or State and a = parsedResponse's type
Hey hey hey, I had never replied to any of your videos because they're simply amazing and flawless (but functors... heheheh). But now I've gotta welcome u to Brazil! You simply made me get up from my chair and go after my wallet to shop my tickets to the conf.. It will be a pleasure to met you at brazil's JS conf!! Keep it up mate!
Thanks for the awesome content. Any chance there are some videos you made out there that aren't in this functional programming's playlist? Would love to keep exploring :)
Wow, not only is this the best explanation for monad's I've seen, flatMap is a far more descriptive and apt name for the action of squeezing the value out of the stream or other container than bind or chain. Probably the only more descriptive term might be "unwrapMap"!
Man i am a big fan of yours, But when i am trying to debug the code for Series 7 i am not able to do that Using : Visual studio code can u please make a video on debugging or can u tell me any better way to achieve that.
Great video! It would be great if you could just show us more examples of monads just to get more exposure to them. Overall great job! Thanks for your work.
Loving this series! Coupled with Prof. Frisby / Dr Boolean and trying stuff out, it's starting to sink in.... slowly, but getting there! I have a small question about the Promise example here though which was confusing at first. You said (around 9:10), something like "what you get back is the parsed object literal and it will pass it onto the next callback" Is that really right? Is what you get back not actually another Promise monad? i.e. you can't call then() on the object literal. I realize the code works and the idea is there, just wondering if I'm missing something in your explanation. In other words... In the stream.flatMap() example, what you get back is another Stream (which you can subsequently map() or flatMap()). Same for promise (you get back another Promise which you can then()). In terms of why this is different than a regular functor, the difference between flatMap() and map() is that if the value returned by the function that was passed to the functor's map function, results in another functor, then flatMap will return a functor mapped with the function that was passed to the inner functor's map. In other words - if we have a function map(f(x)), and f(x) returns a functor, then getting at x requires calling map(map(f(x)). Since flatmap returns a functor mapped with the function that was passed to the inner Functor's map, it reduces that down to map(f(x)). Or something like that? ;)
A good summary that made me more clear about flatMap: flatMap has the same principle as map while the exception is if the callback passed to flatMap returns a monad of the same type of stream monad, that stream monad will be flattened into its containing value before it's passed on. thanks. actually I got what flatMap is, but I didn't Whats the Monad?
I've seen a guy doing dynamic programming using monads. How does that work? I didn't understand much at all. (/watch?v=4q3v2p2-Cmc) He starts rewriting his code at 10:00.
Wow, just had a crazy McDonald's commercial for BigMac. Around 8:30 when you emphasized "it is not called flatMap, it is THEN" the commercial launched and the guy said "it is now and then" and flashes some images of bacon and ended. Way to break your concentration.
With all of us all being front-enders by trade.. I'm really waiting on what I feel is the logical follow-up to this video: Reactive Functional Programming! Getting into it this last week, but haven't been able to find the most clear explanations on it.
+Wil L A monoid is a data type that can be combined in some meaningful way. You can concatenate a list with another list, you can merge 2 streams together. This combining operation must be associative, which means that if I'm combining a chain of monoids together, it doesn't matter which monoids in the chain we merge first, as long as the order of that chain is preserved. For example: array1.concat(array2).concat(array3) // array1 + array2, then the result + array3 is the same as array1.concat(array2.concat(array3)) // array2, + array3, then array1 + the result but NOT the same as array1.concat(array3).concat(array2) // array1 + array3, then the result + array2 In short, a monoid is about this combining operation. A monad is about the "flatmap" operation described in the video.
Thanks for the video! I really enjoyed it. Not just this one but all of them. Huge fan. One question. Is Promise.all implemented with Monads? Is it like flatMapping a bunch of Monads? Thanks again!
+Scott Crossan No, promise.then is literally flatMap. If f return a promise with promise.then(f), it will resolve the promise before chaining the next then. If promise.then worked like map, then the next then would get a promise, not the value inside the promise. To put this in code, let's say we have two promise based api calls, one to fetch a value, another to translate: api.fetchWord() api.translate(word) Let's say fetchWord always returns Promise.resolve("hello") and translate converts "hello" to Promise.resolve("你好") If promise.then is map then: api.fetchWord().then(api.translate) === Promise.resolve(Promise.resolve("你好")) But since promise.then is flatMap, we have: api.fetchWord().then(api.translate) === Promise.resolve("你好")
.then() on promises is exactly the same thing as flatMap, so you can do the same thing with then as you can do with flatMap. Promise.all is really just a convenience method, and you can absolutely implement the same thing using only then's, but it's pretty nice to use Promise.all.
+funfunfunction The problem with .then() is that you don't know if it equivalent to .map() or .flatMap(). In this example it is equivalent to .map(), because you are just transforming the value inside the promise (like a functor), you aren't flattening anything, like when you have a promise of a promise.
+Ronald Chen My understanding was that .then is actually a bit overloaded: it will act like flatMap if you return a promise (or rather, any "thenable"), but it will act like map if you return a value. Most Monads implementations keep these behaviors separate. Promise.resolve(5).then(x=>x+1).then(x=>Promise.resolve(x+2));//->Promise[value:8]
Is a Monad really a Functor? The flatMap can change the structure of the output: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
+Emilio Srougo reading through most of the Bacon API docs I've concluded there is no such mechanism and googling didn't help me either. I guess my understanding of this stuff is just too limited, but I'm very curious about the solution.
+Peter Herdenborg Ok, maybe replacing flatMap() with flatMapConcat (baconjs.github.io/api.html#observable-flatmapconcat) would do the trick. flatMapConcat is equivalent to "flatMapWithConcurrencyLimit(1) (only one input active)". "flatMapWithConcurrencyLimit(limit, f) a super method of flatMap family. It limits the number of open spawned streams and buffers incoming events." I'm not 100% sure this is what we need...
The concept of flatten is weird to me. I think I get it but it seems to me like it would be better explained as just completing a chain of functions that happens internally before returning the result. It would be helpful to better understand exactly what those functions are. It looks like just a map chain until the value is returned. A good idea would be to show what the flattening process involves. I'm not sure if it as simple as this but I'd imagine getting the Bacon.promise objects with map and then map those again?
MPJ, You could do live streams while you code. This way the viewers can interact with you and learn in real time how do you build up an complex algorithm. We could solve problems in opensource projects in github in a collaborative way. What do you think about this?
+Walker Leite I think that most of my audience is asleep when I an awake. ;) it's a great idea, but I have not yet been able to figure out what the logistics would be. I'm on GMT+1 time and a huge chunk of my audience is in the US and Brazil. The only time slot I could think of is Saturday evenings and I'm not super keen on scheduling something on those.
Europe will be grateful for any of those streams. I'm also on GMT+1 and I'm very big fan of yours. Those streams could be recorded and published in place like this: www.livecoding.tv
The video on Functors + this on Monads are very helpful! Ideas for a subsequent related video are : 1) think 'mapFlat' instead of 'flatMap' as flatMap is like map 1st and flatten 2nd ( alvinalexander.com/scala/how-to-combine-map-flatten-flatmap-scala-cookbook ) 2) explain 'flatten' in more depth. I think I've seen that arrays get 'flattened' by just 1 dimension, so for ex a multi-dimensional array could have array.flatten.flatten. (Not positive on that :-) Do objects/classes need to implement their own 'flatten'? 3) Personally, I'd like to see a useful example with Monads that doesn't depend on a 3rd-party library. FYI, saw some interesting flatMap code in discussion at gist.github.com/samgiles/762ee337dff48623e729
Here's a story:
1 I started this video on monads
2 he mentioned functors and said "watch this video if you don't know about functors"
3 I paused the video and opened funtors in a new tab
4 in the functors video he said "if you don't know about maps, watch this video about it"
5 i paused functors and opened the maps video in a new tab.
okay now hold it......... did you notice something?
My time on youtube has turned into a subroutine mechanism....... I find this fascinating :D
Wait until you get to the video about recursion..
Same thing happened to me but luckily earlier in the chain.
So what you're saying is that this video is a Monad, because it flatMaps the recursive promise of previous videos into a final distilled answer to the question of what a Monad is... That's meta.
Haha exact same thing here, pushing a solid 4 hours of going down that chain
@@spacemonk4874 Tail recursion is its own reward! xkcd.com/1270/
So what have we learned from this episode? Portuguese is hard
Wait until you see pretérito imperfeito.
Wait until you see our slangs.
Polish is way worse.
@@rothbardfreedom Wait until you see pretérito mais que perfeito
That was the best monad tutorial I have ever seen.
+John Michael Lafayette this is possibly the nicest thing anybody have ever said to me.
I really mean it. I think that if Gang of Four existed at the same time as Haskell, they would have described it just like you did. Obviously there is more, but your laid out the fundamental concepts in a very straightforward, intuitive way.
that was the geekiest joke i ever seen.
This is the only video that sets fire on our monad appetite for more knowledge. One of the (several) main qualities of funfunfunction videos: passion, appetite, fun.
Dr. Boolean's would be a great next step, if I may say.
For situation like line 30 @6:05, you can just do .onValue(console.log) and that is it.
I love the way you get straight to the point and leave the rest to us curious minds.
If only we had more practical people like you.
Thanks a bunch.
Not only the best monad tutorial that I have ever seen but the best flatMap example that I also have ever seen: from a very complex term called 'Monad' to 'As simple as that'. Cheers for it! I was sick of reading about monads and Haskel.
oh man, I'm so happy I found you and DevTips, you guys are taking youtube tutorials to a new level, making it super entertaining even serious and advanced subjects like this.
You really seem to give way more importance to the learning experience than to the "look-how-good-I-am-at-this-I-learned-it-from-boring-docs-and-you-dont-deserve-to-learn-it-in-a-less-boring-way" kind of feeling
Looking forward to see you here in Brazil!
I like how concise and distilled the explanation of monads was delivered yet was still chocked full of sweet streaming and promises morsels. Well done mate.
+atxaqualion75 thanks a ton!
+atxaqualion75 thanks a ton!
Ah, FINALLY! Thank you so much for pulling me out of the category-theory hole I was digging.
I don't understand why the ouput is different from 6:51 --> Cat, Meal, Trumpet and 8:05 --> Trumpet, Meal, Cat ?
Probably because it's being run through an API call before logging out the response, so the order is going to be random based on whichever API response arrives first.
const yodify = (noun, verb, complement) => {
stream.push(noun)
setTimeout(() => stream.push(verb), 745)
stream.push(complement)
}
yodify('Tesla', 'is', 'a genius')
Don't ever stop making videos. You have the best js series, by far! Everything is well put together, informative, and entertaining. I have been a professional coder for 17 years, and still find lots of value in your videos. I even made my wife watch your episode on "Too many frameworks", just for the cookies comment. haha
Thanks for the explanation linking monads, 'bind', 'chain', and 'then'. That definitely helps tons. One question. Since 'then' has flatMapped the promise response into JSON in line 15 (around 8:42), would we be able to use 'map' instead of 'then' in line 16, and get the same result?
const promise = fetch(url)
.then(response =>respons.json())
.map(parsedResponse =>
....
+Dan Williams Not out of the box, because Promises don't implement a literal .map method. However, .then will work exactly AS map as long as you're careful about what type of value you return (as long as it isn't a Promise: i.e. as long as it isn't something that implements then, basically).
You could Promise.prototype.map = Promise.prototype.then, of course, but... don't. Probably just remember that .then is overloaded.
Just for fun, do implement .ap though!
Promise.prototype.ap = function(p){
return p.then(x => this.then(fn => fn(x)) );
}
var addTwo = curry((x,y)=>x+y);
var delay = (v,n) => new Promise(r=> setTimeout(_=>r(v), n));
Promise.resolve(addTwo)
.ap(delay(4,1000))
.ap(delay(6,3000))
.then(x=>console.log(x));//-> after both delays complete, the values are added and returned!
+Drew Tipson Interesting insight Drew! Then since Promises don't technically implement map, are they still functors? Are all monads functors by default? Is flatMap enough to justify the title?
+Dan Williams I would argue that they are still Functors, but here, particular to Javascript, we have a distinction between the implementation vs. the theory. I'd argue that just because the method name of something isn't literally the string key "map" doesn't mean that something isn't a Functor: it implements the Functor interface map, and it passes the Functor laws, so it's a Functor, end of story, in my book! I mean, if you wrote an entire language language that used non-English words, .map wouldn't be Functor["map"] it'd be, say, Functor["mapa"]. But it'd still be a Functor.
However, there's the issue of coordination to consider in javascript. In higher-order operations, we'd like to be able to pass a Functor, ANY functor off into a function, and know that we can use a map operation on it just by calling Functor.map(f). If it's not literally available at ["map"] though, that coordination won't work! We run into this naming problem all the time both when extending the spec (ES7's "Array.includes" should have been called "Array.contains" but couldn't be, for instance, because that method name was being baked into the Array prototype all over the web with a different type signature/behavior) and developing pointfree wrappers for all Functor and Monad types: should we call flatMap bind? Nope, we can't do that, since that already exists and does something totally different. .flatMap? .chain? Maybe, but all those decisions have consequences for, again, larger-scale coordination. Most of the functional JS world seems to have settled on calling bind "chain." But ES(8?) may include native .flatMap and .flatten methods on Arrays, which means that yet again, we could be headed for having the same things used with different names.
So to the question of whether all Monads are Functors: yes they definitely are! That's because once you have a .flatMap that passes all the Monad laws, you can derive .map "for free" by composing the pointed function (Monad.of) with the mapping function and just passing that to flatMap/chain. But again, we hit the possibility that, in Javascript, it's certainly _possible_ to define a legit Monad but not actually _expose_ a Functor implementation, even though it'd be trivial to do so! And Promises are exactly such a case: not only is a .map implementation possible, it's actually implemented. But it's called .then (which is ALSO flatMap!) instead. So in some pointfree wrappers, you might even see things like const map = curry((f, xs) => xs[xs.map?"map":"then"](f) ); which will try to use map if available, but then to handle the Promise case, fall back to trying then instead.
As I understand it, in a language like Haskell, you don't run into this problem because the type system builds these packages onto each other directly: once you've defined a Monad you by default have a map interface for it out of the box. But with javascript, it's all loosey-goosey: you can define whatever methods you want on anything, and there's no type system to enforce proper behavior. You could easily define a method on something called map that doesn't obey the functor laws and nobody can stop you.
First description without any mention of category therory. Well done MPJ
I wonder how interop could be achieved? I mean I would have to cast everything to bacon streams if I want to use bacon's flatMap implementation right? Just like I have to cast everything into a Promise if using `then`. I doubt there is a better way, right?
Just watched whole functional programming series in like 3 hours after I found out this channel. I'm feeling like understanding at least 90% of it, and thats because most of it was really, really similar to Java8 streams and lambda expressions. And of course because episodes are really, really cool!
Ok, I went through your Functional Programming series and you asked for it, so I'll give it to you.
I'm interested in Functional Programming because I want to learn how to make small simple bits of code and re-use it all over the place without making a Moebius surface out of my code.
So my current constraints are: I'm programming in IBM's RPGLE, procedural, strongly typed, compiled language and my employer restricts the use of procedures (an equivalent of a function, he has his reasons). He is going to open the door to DB2 SQL procedures and here is where I want to create useful, re-usable, beautiful functions that will be used all over the place.
My worry is creating functions that aren't composable and ending up with one big useless library that won't be re-usable, ending up with tons of copies of each procedure, for every new scenario.
I want to ask you to give me pointers on how to think, the rules of thumb, good practices, how you keep data and functions separated and where do they connect. I know this is a tall order, but you do like recipes xD
Thanks for the rest of the videos, I feel they gave me some insight into this question, but I feel I still need more.
Keep up the good work ;)
Thanks, defiantly the best beginner introduction to monads that I have seen that is not cursed with the "curse of the monad" ("curse of the monad": once you understand what a monad is, you lose the ability to teach or explain what a monad is)
my confusion is if Promise does implement flatMap, then how it implements a map,
according to your definition , it is monad only if it implements both
.then implements map and flatMap in one. I’m playing a little fast and loose with the definition and many would say it’s not strictly a monad, but I think that’s being correct to the point of uselessness - in practice, it’s a monad.
So we can say that , flatMap is general to Promises,
but when we talk about Map
.then(result => Promise.resolve(result.item))
would enact the map part of a monad
Hmm, your statement does not make sense for me, sorry.
.then will do the job of both map and flatMap without modification:
.then(result => result.item) //map, expects callback to return non-monadic value
.then(result => downloadImage(result.item.avatarUrl)) //flatMap, expects callback to return monad, which flatMap will unwrap
Ok gotcha , its make sense now , i was missing a lil concepts on promises, thanks :)
Dude, explaining monads always sound 100% confusingly terrifying for me, now it's just 98%. BUT YOU DID A GREAT JOB, now I can start explaining what is a monad. And a functor. GOOD!
I come from a Python background so the native async processing in js confuses me sometimes. But how can I make sure that the values in the stream are processed in the order they were pushed without having to wait for each value to resolve?
Eduardo Tenorio That doesnt seem beginner friendly to me. ((But I'll admit that this can be used to massively increase performance ))
Eduardo Tenorio Yes, but it is not inbuilt and also _should_ preserve order in lists
Eduardo Tenorio Well asyncio is included in the standard interpreter for python but is not as depending as JS. And it might actually be both since lists are not promises and therefore not interfere with Pythons definition.
I guess you could use "Promise.all" and get in return an array of results in the order you provided them to the ".all" method.
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
you are the MAN. i started of by learning Category theory from a Math theory video and i almost died. This actually makes sense. great video.
oooh this is the best of feedback, thank you 💛
So es6 Promise is a monad not a functor? Does that make sense?
What if the function passed to stream.flattMap returns a promise instead of a stream?
Thanks for the video!
It would simply return the unresolved promises. flatMap will not flatten ANY monad, only monad of the same type. flatMap on a stream will only flatten streams, just like .then on a promise will only flatten promises.
You definitely make programming concepts easier and more fun. Your videos are changing the way I think about programming so I'll make sure to thank you in person when you come to Brazil!
I find a graphical representation of streams within streams, and the flattening of these makes people get it faster. also relating it to arrays and concat + map
thanks for this video and the other two about Functors. This was what I was looking for, a pratical and applied programming point of view about Monads, not just another complex mathematical definition. This helped a lot. Thanks!
Great explanation. I think if I'd watched this before trying to learn monads from other sources, they would have made a lot more sense earlier on. It's so helpful to have a simple idea to fall back on when learning something (I.e. at least I know "this" about it). Kinda like a set of coat hooks to hang all the details on. I think that's the "get monads" idea you were talking about.
I finish the series of functional programming and i learn a lot and level up my js skill so THANK YOU MPJ
I'm still not clear on monads. What's being flattened?
Did you watch the previous videos?
i don't understand the "super powers" of the monads on haskell to do side effects just with them, ... that's what is really really confusing
It is easy to learn something when you actually need it. It's like reinventing the wheel because you didn't care what a wheel is and never needed one. Then you make the wheel and share your findings, but everyone else says it was already invented and they tried to tell you that... Monads, monoids, semigroups and many other math concepts are just that. If you try to write a program that does symbolic computations you'll probably learn all these concepts on the way and they will be quite natural and useful. I like haskell because it uses correct names for most things and many design choices are really good. I like the modules exporting things and when you import something you can specify what exactly you want to import. Another cool thing is "qualified" keyword. Instead of putting everything in a library in a namespace(as you would do in C++) you specify the namespace when you import it!
More about a functional programming and monads you can read here github.com/xgrommx/awesome-functional-programming
Is there an example of an useful functor that couldn't be implemented as a monad? Instead of simply deliberately removing the chain/flatmap from a monad?
You are awesome sir. Thank you for spending your time to make these videos! Thumbs up for picking up Portuguese in this example haha.
+Andre Varandas obrigado!
@funfunfunction Do you use frp techniques on your daily programming basis?
How can I use these super powers in the enterprise world? Like maybe even in server-side code too? (I do full stack .NET code with C#/typescript (with Knockout to bind our viewModels)). I like these ideas and want to use them! We kind of use some of them in our typescript code, and we use bluebird for promises (so we use then callbacks and all that jazz), but I feel like I don't use these things in everyday code (except with our super nice postJsonPromise), but maybe using promises and stuff is the answer (I don't think I can use F# :c).
Check out Eric Lippert's series of posts on monads in C#.
ericlippert.com/category/monads/
Check out Eric Lippert's series of posts on monads in C#.
ericlippert.com/category/monads/
Is there a standard for which property is returned for each item when calling flatMap? Eg would it always be "value":
{
value: "this would be returned",
otherValue: "this wouldn't"
}
Or do you just have to take a look at the method?
There is very strict rules for it in Haskell (it's what people refer to with the monad laws) but seen across all languages it is really just whatever value is contained within the monad. Think of it conceptually rather than the name of a property on an object or something. The monad, a stream or a promise or or some other, is a kind of box that contain a value or values, and mapping it is a way of getting to those values, and flatMapping is a way of combining those values with other monads of the same type. Sort of. ;) this is something that you just have to do a bit in different ways until you find an explanation that works for you personally.
+funfunfunction thanks :)
This was interesting.
I think the follow up video should showcase more practical examples of useful applications of monads. As often, the most important is not only to understand how a tool works, but to build an intuition on when it's appropriate to use it.
+Feakos this! +funfunfunction
Monads are interesting, but it gets a bit confusing when applying them in languages such as Python and JS.
+Feakos this! +funfunfunction
Monads are interesting, but it gets a bit confusing when applying them in languages such as Python and JS.
+Feakos I think you already have got the idea about where you can use it. Waiting for promises to return is a fantastic example shown here
Monads are a higher transformation of an object or entity, through functions, were we can do extra computation.
In this video that "extra computation" is the "flat"
I think I understand the functions your using, map and flatMap, and .then. So a monad is a functor that takes an unresolved structure, like a stream or promise, and allows it to resolve before subsequent instructions can proceed. Do I have that right?
I don't think the unresolved part is a requirement, the return just has to be 'wrapped' in something.
+James MacIvor, not strictly right because monads aren't necessarily async but good approach. Monads are for composing functionalities depending of a run time value. One way of understanding monads is separating promise then() in three functionalities. map() is for transforming the values inside the promise (only if it is resolved), for example toUppercase. flatMap() (or chain()) is for composing promises, for example fetch a value from a server and based on that run time value make another fetch. Finally then() is when all chained promises are resolved, make something with that value. Take a look to folktale Task or ramda Future, they have a clean separation of three functionalities.
So a promise is a monad that implements then instead of flatMap. What are other examples of useful monad like things?
+Anastasi Bakolias I'd say: implements .flatMap() AS .then(), rather than instead of.
One more thing being a monad gets you is the ability to define an applicative method (and thus if the monad contains a unary function or a curried function instead of a value, you can pass it its values each also wrapped in Monadic context and then get a Monad of the same type out containing the result)
I noticed the order changed in the output. Does a flatMap not guarantee order?
Answered in other comment
How does this relates to the IO monad from haskell?
After watching #10 an #11.... yeah, that made sense... Interesting (or not, maybe just silly) question:
Why did the words order change when you added the map with the toUpperCase()?
Wow! Great episode! Makes idea and concept of monads very clear, and fits in just 11 minutes!
Thank you for the work you do!
Any chance of sharing the screen layout app that you are using for the videos?
It's just a PNG + Uberlayer. I've tested every single layout app and none of them gives the pixel-perfection that I need for the videos. You can check the gear + behind the scenes videos for more info.
What I don't seem to get immediately is that if a simple map returns the stream unflattened, shouldn't it also show its enclosing value?
+enyaWrMMrWayne can you please elaborate on your thoughts? I'm not sure I understand the question.
+funfunfunction Sure. Before applying flatmap we see that Bacon.fromPromise({}) is returned. Instead of empty brackets I expected to see Bacon.fromPromise({cat}), ie the unflattened stream. This obviously isn't the case and i was wondering why. Thanks for the reply
+Themis Papavasileiou the thing is, before flattening the stream, we don't know what is in it. There is no way map could do what you ask, because the cat has not "arrived" yet. There is nothing in the stream at that point in time.
flatMap will understand that the return value is a stream, and wait for stream to end, but map will not have that extra cleverness, and return it immideately, before there is something "in" the stream.
+funfunfunction seems that I chose to forget the async of it all :P i get it now thanks
glad to be of service!
Can someone clear this up for me? I don't understand how methods like map and flatMap work can work for streams. Do they wait until the stream is finished receiving all data before it moves on to the next method? For example, stream.flatMap().map(toUppercase); ? What if the stream receives more data as it is in the process of performing flatMap and map? Thanks!
The stream processes as it goes. If you watch closely, you can see that the values are not coming out in the same order as they come in, which is because the network requests are coming in at different times. Some stream operations cannot be performed until the stream has ended, like say, a sort, or toArray, but the operation in the example can be performed as the items come in.
+funfunfunction Thanks, that makes perfect sense! Keep up the awesome videos.
With what other names we can find monad?
"refeição" is read like this: ray(-y)+fay+sound(-d).
great explanation, btw :D
"hay" works better.
depends on the dialect... brazil is a big place
Capaz mesmo! ;)
Using swedish letters you would pronounce it like: He-fej-så
Streams are nuts. No idea how I could live up until now without knowing them.
Could you tell me why do I need them if promises give me all everything I need? I see lots of info about streams, how to use them, but I don't see WHY.. If I need to do http request I just use promise, WHY do I want to do stream......?
Promises can only produce one value. A stream can produce any number of values. A stream can do everything a promise can do, but the reverse is not true.
@@_ericelliott I read composing software before seeing these videos! Love you both!
Wow, I’m just starting to get this stuff looking at the Haskell side of things, but I never realized that Promise/.then is just that too!
Hello from the future. I just watched the whole playlist at one go and I am very appreciate because i realy GET IT
hi, thanks for the vidoe but I'm still lost, what is a monad? when did you explain it?
Did you watch the previous videos in the series? You might also might to watch my monad talk on nordic.js that is a later narrative.
This is the seventh explanation of monads I'm seeing and the only one which makes sense.
In fact it seems so easy and so unrelated to previous ones that I'm kinda suspicious that it's not actually about monads.
I have been watching your videos and this is the best. why? Using portuguese words you show us wich you know the brazilian desire to learn js! But we, brazilians, has two challenges: learn english and after learn JS! Thx by your videos and your wonderful english, i'm learning coding and languages!
For all you JavaScript or Python Twisted programmers who do async code using callbacks/promises/futures, "then" is monadic bind is flatMap! In Haskell you use then aka >>= for both synchronous code (IO,State) and async code that way you "transform" your async code to be synchronous code to and back again, and add "semantics". Basically Monads allow you to abstract away the semantics of your "sequential" code allowing it to evolve independently from your code itself. - EDITED - lol then is right there and I didn't even notice that. The types are very similar for flatMap / >>= and then m a -> (a -> m b) -> m b, where m = Promise instead of IO, List, Maybe, or State and a = parsedResponse's type
Monad is a functor that realizes "of" and "join" methods. "Flatmap/chain" is a combination of "map" and "join".
Thanks for the video, but why does flatmap reverse the order of the stream?
It doesn't, that's just a coincidence. The stream comes out in the order that the network requests from the Google translate Api comes back. ;)
+funfunfunction thanks a lot, I should have thought of that ;D
Thank you for the constant inspiration! And musings. I've a lot of episodes to catch up on.
Hey hey hey, I had never replied to any of your videos because they're simply amazing and flawless (but functors... heheheh).
But now I've gotta welcome u to Brazil!
You simply made me get up from my chair and go after my wallet to shop my tickets to the conf.. It will be a pleasure to met you at brazil's JS conf!!
Keep it up mate!
Wow, that is awesome! Hope to see you there!
Thanks for the awesome content. Any chance there are some videos you made out there that aren't in this functional programming's playlist?
Would love to keep exploring :)
Wow, not only is this the best explanation for monad's I've seen, flatMap is a far more descriptive and apt name for the action of squeezing the value out of the stream or other container than bind or chain. Probably the only more descriptive term might be "unwrapMap"!
+nERVEcenter117 I really like your wording of sneezing it upwards and calling it unwrapmap!
Man i am a big fan of yours, But when i am trying to debug the code for Series 7 i am not able to do that
Using : Visual studio code
can u please make a video on debugging or can u tell me any better way to achieve that.
Does this have anything to do with the monad discussed by Liebniz, the 17th century mathematician?
+Adam S monads have its origins in Category theory, a branch of math. Not sure if that is the same thing that Liebniz talked about.
why does the word for "cat" drop to the end of the list in the last example?
oh, never mind. It's probably because google translate responded a bit slower with that word on that run.
+Toby A correct!!!
All of your tutorials are awesome!
I'd love to know what software you use to make them. :)
+Michael Johnson thanks! Check out the behind the scenes episode.
Thank you!
It is so easy to understand, I can't understand the reason of the complexity of other explanations... any hints?
You have a great style of teaching.
Oh. It means "Evaluate the complete expression, you lazy intepreter."
can u make a video on sorting
For information, native JS Array.flatMap does not resolve promises like Bacon does.
Great video! It would be great if you could just show us more examples of monads just to get more exposure to them. Overall great job! Thanks for your work.
Wow! Your videos are on Creative Commons licence. It's super fantastic! Thank you! :)
Loving this series! Coupled with Prof. Frisby / Dr Boolean and trying stuff out, it's starting to sink in.... slowly, but getting there! I have a small question about the Promise example here though which was confusing at first.
You said (around 9:10), something like "what you get back is the parsed object literal and it will pass it onto the next callback"
Is that really right? Is what you get back not actually another Promise monad? i.e. you can't call then() on the object literal.
I realize the code works and the idea is there, just wondering if I'm missing something in your explanation. In other words...
In the stream.flatMap() example, what you get back is another Stream (which you can subsequently map() or flatMap()). Same for promise (you get back another Promise which you can then()).
In terms of why this is different than a regular functor, the difference between flatMap() and map() is that if the value returned by the function that was passed to the functor's map function, results in another functor, then flatMap will return a functor mapped with the function that was passed to the inner functor's map.
In other words - if we have a function map(f(x)), and f(x) returns a functor, then getting at x requires calling map(map(f(x)). Since flatmap returns a functor mapped with the function that was passed to the inner Functor's map, it reduces that down to map(f(x)).
Or something like that? ;)
A good summary that made me more clear about flatMap:
flatMap has the same principle as map while the exception is if the callback passed to flatMap returns a monad of the same type of stream monad, that stream monad will be flattened into its containing value before it's passed on.
thanks.
actually I got what flatMap is, but I didn't Whats the Monad?
I've seen a guy doing dynamic programming using monads. How does that work? I didn't understand much at all.
(/watch?v=4q3v2p2-Cmc) He starts rewriting his code at 10:00.
+Shadow4707 that was really helpful even if you know no haskell at all (i.e. me). Stick around up to the 17th minute mark, it all ties together !
Wow, just had a crazy McDonald's commercial for BigMac. Around 8:30 when you emphasized "it is not called flatMap, it is THEN" the commercial launched and the guy said "it is now and then" and flashes some images of bacon and ended.
Way to break your concentration.
Can't be this easy. :-) Shouldn't monads be able to chain (ala underscore) or something?
I like how you explain things. Also nicely made video! Cool application. More please! :)
So what are some examples of functors that are not monads?
+Mark Kessler Array, for example.
But array of arrays? :P
With all of us all being front-enders by trade.. I'm really waiting on what I feel is the logical follow-up to this video: Reactive Functional Programming!
Getting into it this last week, but haven't been able to find the most clear explanations on it.
What console do you use?
I may have missed it but, monoid vs. monad?
+Wil L
A monoid is a data type that can be combined in some meaningful way. You can concatenate a list with another list, you can merge 2 streams together. This combining operation must be associative, which means that if I'm combining a chain of monoids together, it doesn't matter which monoids in the chain we merge first, as long as the order of that chain is preserved. For example:
array1.concat(array2).concat(array3) // array1 + array2, then the result + array3
is the same as
array1.concat(array2.concat(array3)) // array2, + array3, then array1 + the result
but NOT the same as
array1.concat(array3).concat(array2) // array1 + array3, then the result + array2
In short, a monoid is about this combining operation. A monad is about the "flatmap" operation described in the video.
+Shayden Martin Ok, soon I'll understand what I'm doing :) thank you.
What is your IDE?
Thanks for the video! I really enjoyed it. Not just this one but all of them. Huge fan.
One question. Is Promise.all implemented with Monads? Is it like flatMapping a bunch of Monads?
Thanks again!
Great video I think I now understand what a monad is. Am I right in thinking that flatMap could be used as a replacement for Promise.All?
+Scott Crossan No, promise.then is literally flatMap. If f return a promise with promise.then(f), it will resolve the promise before chaining the next then. If promise.then worked like map, then the next then would get a promise, not the value inside the promise.
To put this in code, let's say we have two promise based api calls, one to fetch a value, another to translate:
api.fetchWord()
api.translate(word)
Let's say fetchWord always returns Promise.resolve("hello")
and translate converts "hello" to Promise.resolve("你好")
If promise.then is map then:
api.fetchWord().then(api.translate) === Promise.resolve(Promise.resolve("你好"))
But since promise.then is flatMap, we have:
api.fetchWord().then(api.translate) === Promise.resolve("你好")
.then() on promises is exactly the same thing as flatMap, so you can do the same thing with then as you can do with flatMap. Promise.all is really just a convenience method, and you can absolutely implement the same thing using only then's, but it's pretty nice to use Promise.all.
+funfunfunction ok well I'm currently in hospital but when I'm out I'll have to play around with flatMap
+funfunfunction The problem with .then() is that you don't know if it equivalent to .map() or .flatMap(). In this example it is equivalent to .map(), because you are just transforming the value inside the promise (like a functor), you aren't flattening anything, like when you have a promise of a promise.
+Ronald Chen My understanding was that .then is actually a bit overloaded: it will act like flatMap if you return a promise (or rather, any "thenable"), but it will act like map if you return a value. Most Monads implementations keep these behaviors separate.
Promise.resolve(5).then(x=>x+1).then(x=>Promise.resolve(x+2));//->Promise[value:8]
Omg, this is the closest i have felt of understanding what a monad is!
Is a Monad really a Functor?
The flatMap can change the structure of the output: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
Why don't the translations log in order?
They log as the api requests come back. Homework for you: how can you fix that using Bacon?
Because the 'getInPortuguese' function is asynchronous and the values are emitted in the order of the responses, not the requests' order ;)
+funfunfunction I don't know. How?
+Emilio Srougo reading through most of the Bacon API docs I've concluded there is no such mechanism and googling didn't help me either. I guess my understanding of this stuff is just too limited, but I'm very curious about the solution.
+Peter Herdenborg Ok, maybe replacing flatMap() with flatMapConcat (baconjs.github.io/api.html#observable-flatmapconcat) would do the trick. flatMapConcat is equivalent to "flatMapWithConcurrencyLimit(1) (only one input active)". "flatMapWithConcurrencyLimit(limit, f) a super method of flatMap family. It limits the number of open spawned streams and buffers incoming events." I'm not 100% sure this is what we need...
The concept of flatten is weird to me. I think I get it but it seems to me like it would be better explained as just completing a chain of functions that happens internally before returning the result. It would be helpful to better understand exactly what those functions are. It looks like just a map chain until the value is returned. A good idea would be to show what the flattening process involves. I'm not sure if it as simple as this but I'd imagine getting the Bacon.promise objects with map and then map those again?
MPJ, You could do live streams while you code. This way the viewers can interact with you and learn in real time how do you build up an complex algorithm. We could solve problems in opensource projects in github in a collaborative way. What do you think about this?
+Walker Leite I think that most of my audience is asleep when I an awake. ;) it's a great idea, but I have not yet been able to figure out what the logistics would be. I'm on GMT+1 time and a huge chunk of my audience is in the US and Brazil. The only time slot I could think of is Saturday evenings and I'm not super keen on scheduling something on those.
Europe will be grateful for any of those streams. I'm also on GMT+1 and I'm very big fan of yours. Those streams could be recorded and published in place like this: www.livecoding.tv
People: no one can explain monad easily
This video: u sure?
Your videos are so great with good knowledge! Thanks
nice
btw what is that editor?
+Hoto Looks like Atom.
Hey Lpj! Love your lessons, thanks for the functionnal ones! :)
your tutorials are amazing man, keep up the good work!! btw, what's the song? love it!
mmmmmmm bacon stream
My many thanks to you for doing this
The video on Functors + this on Monads are very helpful! Ideas for a subsequent related video are :
1) think 'mapFlat' instead of 'flatMap' as flatMap is like map 1st and flatten 2nd ( alvinalexander.com/scala/how-to-combine-map-flatten-flatmap-scala-cookbook )
2) explain 'flatten' in more depth. I think I've seen that arrays get 'flattened' by just 1 dimension, so for ex a multi-dimensional array could have array.flatten.flatten. (Not positive on that :-) Do objects/classes need to implement their own 'flatten'?
3) Personally, I'd like to see a useful example with Monads that doesn't depend on a 3rd-party library. FYI, saw some interesting flatMap code in discussion at gist.github.com/samgiles/762ee337dff48623e729