Check out a free preview of the full Hardcore Functional Programming in JavaScript course:
The "Other Functors" Lesson is part of the full, Hardcore Functional Programming in JavaScript course featured in this preview video. Here's what you'd learn in this lesson:

Brian breezes through a few more functors. EventStream provides an infinite list of results. Future has an eventual value similar to a Promise, except it's "lazy".

Get Unlimited Access Now

Transcript from the "Other Functors" Lesson

[00:00:00]
>> [MUSIC]

[00:00:04]
>> Brian Lonsdorf: We'll go over these pretty quick. It's about the same as every single thing else that we have been looking at. But there are other functors out there. We've seen null checks and IO, and air handling with either. We have EventStreams which could be, you could translate, a list, an event you say add event listener.

[00:00:30] You can't compose add event listener, that doesn't do anything. It's like run this function every time. Well, run this function every time this thing happens, that sounds like a map to me. What if I compose an EventStream of every click on the screen, then I can map over that.

[00:00:44] It's just the same as add event listener, run this function. But I have an EventStream out of it, and I can keep composing that. So let's look how that works. We use Bacon here, which is probably the most popular except for RxJS, works similarly anyway, different names. Bacon just has it's own weird API to get click events and what not.

[00:01:05] That's one way to do it. This way is kinda neat, cuz I don't have to get the element first. I can just say get all the clicks on the document. And then we just say, yeah, hey, anytime there's a click on the document, return me the ID with the pound in front of it.

[00:01:22] So I get an EventStream of strings. Now, that top line where we actually map the turning it into an ID, that would be the same as add event listener, document click, run this function, make an ID. But what we get with streams is a tangible object just like we had with all the other functors that we can compose and map over.

[00:01:47] So now we have this EventStream of strings, cuz it transformed those clicks into IDs. And it's all lazy, nothing happens until we call onValue down at the bottom, which kicks off a subscription, really starts listening, and we'll run that for every time that happens. Let's look at another example.

[00:02:09] So just like we're returning, we're mapping those things into IDs, now we're actually running query selectors on it. We can map again, right? Cuz it's still just an EventStream. That's what the _s is supposed to kind of denote. So we've got this EventStream of IDs coming through, and we can find them.

[00:02:24] Now we've got an EventStream of elements. So whenever you click something, I get a element coming through. And down at the bottom, I subscribe to it with onValue, and I'll just alert the innerHTML of the element. And that's pretty neat. Notice that I could have just mapped once and got the ID selector.

[00:02:43] But I'm mapping twice. It's like a composition, right? We talked about that a little bit map, and map. And map is like a kind of composition over functors. And you can kind of choose which way to do it, but just know that every time you map over it, you get a new EventStream.

[00:02:59] And here's kind of a crazier example, this is the last one I'll show before we go on to the next. But maybe there's one more, yeah. The point of this one is to show that I can keep mapping over this EventStream, and it just keeps transforming the EventStream.

[00:03:15] So we've got these hovers, right? And I've got a stream of hovers, and we'll get their IDs, and we'll turn it into query selectors just like we did in the other example. And then we're gonna actually get their post ID from the elements, and then we'll get the API call.

[00:03:34] And none of it happens. It's all totally pure. So, you can you do crazy stuff like that. It's kind of the reactive FRP stuff everybody's talking about. All this stuff is kind of wired together that whenever some hover happens, the rest of it kicks off. Except nothing happens, until I call onValue.

[00:03:54]
>> Speaker 2: Hey, Brian.
>> Brian Lonsdorf: Yo?
>> Speaker 2: There was a question in chat. What is this Bacon library that has this from event target?
>> Brian Lonsdorf: It's just an EventStream library. There's RxJS, Bacon. There's bunch of libraries out there that you can look up that have these things.
>> Speaker 2: It's basically event delegation, and all of the events roll up into a stream.

[00:04:15]
>> Brian Lonsdorf: Yeah, but it's a object, so you can do crazy stuff-
>> Speaker 3: [CROSSTALK] Map over every event on the page that's within the document.
>> Brian Lonsdorf: That's right, and we'll be going over some of the libraries, and you'll be able to take the GitHub code and actually look at all these examples, and all the stuff.

[00:04:32] So, don't get too hung up on where is that, I need that right now. Well, you'll get it. It's cool. [LAUGH] So, yeah, notice I snuck a little future in there. We're about to talk about that. So we get the ProductById. The thing that I thought was important to show was that this whole app won't run until a hover happens, and I finally subscribe.

[00:04:54] Well, I just say alert, so it's gonna alert whatever post or product comes through or whatever. All right, moving on, we're gonna do examples of EventStreams and futures in a minute, and it's gonna feel exactly like the other functors, so no big deal. I'll just do it them cuz we gotta hurry, sorry.

[00:05:10] So we have this future of an eventual value. This is just like a promise, but it's lazy. So it's just like kinda IO in that way. It's got IO rolled into it, cuz when are you going to get some future value and it's not gonna be IO? Like you're gonna read a file, make an API call, I guess there's one case where you have maybe a long running calculation.

[00:05:36] But nine times out of ten, it's a future value that will be some side effect and it'll come back eventually with a value, right? So just like EventStreams, just like IOs, these things build up computations, and they don't run until you kick it off with this fork method.

[00:05:55] So let's look at that. So if I do a http.get of posts, that'll return me a future. And then we'll just map makeHtml with the post from the future. [LAUGH] So this is the alternative to a callback, and promises work the exact same way. If this returned a promise, I could map make Html over the value inside of that.

[00:06:23] So it's just like then on a promise. The idea is that we map this function over the eventual result. Now, this fork thing is where it gets weird. The whole app is gonna look like this stuff above here. But the very end of the line is gonna have this fork of where you are either gonna have an error, or whatever the result of this makeHtml, which is the page.

[00:06:49] That's an important concept cuz futures will fail. There's a good chance your future is gonna fail, whether it's an API call or reading a file that might not be there, or whatever else. So, they've kind of rolled IO and either into this one type kind of, where you're either gonna have your error or your future value.

[00:07:08] And it's all lazy, I have to call fork. It's just like run IO. I say like, now do it. So let's look at the next one. Here we've got our, whoops, same idea. We're gonna get our post, which is gonna return us a future. And then, we're gonna map(createPage) over it.

[00:07:32] And we're gonna get the title of the post, make some HTML, whatever, keep mapping things, doing whatever. And sure enough, down at the bottom, we actually do some effect with it. We're gonna put it on the page. You can't just get the value now, it's not gonna be there.

[00:07:46] You have to map things over it and eventually use it. And that's an important concept with any functor, is that at the end of the line, this is the impure code. All this stuff on the that's your app, and it's all pure, and it's all wonderful, and you can just treat it like it's there.

[00:08:02] Boom, you finally call it, and it's either gonna blow up or not, all right?
>> Speaker 2: People are confused where the future is, but that's http.get.
>> Brian Lonsdorf: Yes, http.get is gonna return a future. I didn't actually, explicitly, make a future here, because it's a little bit weird to look at.

[00:08:17] And I will guarantee you nine times out of ten, even if you're using promises or whatever, the HTTP library, or the read file, or the whatever you're using, is gonna return you a promise or a future, or whatever. So you don't have to really be making them all the time yourself.

[00:08:31] So just know that this return to future, so you have to map over it. What else would we do? [LAUGH]
>> Speaker 2: They're wondering what what is this http.get library, where is that coming from?
>> Brian Lonsdorf: You guys, it's not real. [LAUGH]
>> Speaker 3: It's pseudo code, [CROSSTALK] normally.
>> Brian Lonsdorf: Yeah, hang on tight, we're gonna do the demo soon, that's why I'm-

[00:08:51]
>> Speaker 3: [CROSSTALK] Sorry
>> Brian Lonsdorf: Yeah, that's why I'm running through this really quickly, it's cuz we're gonna go use the demo, and you'll see a real future and a real HTTP. And here, in the jsbin right here, I'm just gonna fake it with a set timeout, but you can go look at that.

[00:09:06] I just wanted to point out this last one, readFile. If you're in Node, this stuff is awesome. If you're in Node, everything is asynchronous all the time, and it's a pain in the butt. And this stuff where you're saying, hey, read the file and then map over it makes it so much simpler than this callback hell.

[00:09:27] This solves that for you. And you can do a lot more than just combine them. And they adhere to the functor and we'll see monoid, implicative, and monad interface as well. So you can do all sorts of crazy stuff with these things.
>> Speaker 3: Isn't in Node there an easy utility that you can wrap around native functions and get back a new function that returns the functor?

[00:09:51]
>> Brian Lonsdorf: Oftentimes, promise libraries give you that. You could probably do the same thing with futures. The difference between the promise and the future is the promise, it's like you have to run it at the end. And that's this fork, error function, or a success function.