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

Brian continues building the CLI blog and uses different forms of function modeling to refactor code, such as the fix type.

Get Unlimited Access Now

Transcript from the "Refactoring Recursive Tasks" Lesson

>> This is our sketch, and let's look at the type of these functions. So now I have a thing that's a function, it returns a task, it takes nothing and returns a task. Holding another function that takes a task, holding another function that takes a task, we've got this recursive type here.

[00:00:22] So that's interesting, how about this one? Same exact thing, it's a function that returns a task that's holding a function returning a task, same with start, okay? What if we decide to call these things. Now, we know what happens. Now it's a function that returns a task. I'm omitting the error side.

[00:00:54] Like task is like error and sum value. So let's just focus on what the task is holding though, task is holding another task, which is holding another task, which is holding another task. But this is menu, when we call it in the function, yeah, becomes the task, right?

[00:01:11] So it's a recursive data structure of test holding tasks. So I happen to know if we specialize task, that's one thing. But if we turn this into any old monad, we get we get that right? And if we take unit and say it takes any a returns that, we can start to look at thes types in different ways, right?

[00:01:39] There's a type called Fix. Let's see if we can, well, the type of fix is like Fix f, f (Fix f), so we can do and say, f is some functor. So in this case, it's like Task. And then it would be Task (Fix Task). And the fix point just kinda promises we're gonna hit a end at some point.

[00:02:12] We'll hit a fix point of this functor. You can keep recursing down until it finally ends. So that's an option. But one thing I do know about fix is we didn't talk about this today. I'm just looking at the types. But the reason I'm gonna rule out fix right now is because it must hold a traversable to be able to do some actual monadic stuff inside it.

[00:02:40] And since task is a monad and not a functor, we're gonna be using it as a monad. I'm gonna back away, but turns out fix has a very close relative called free. And that is a monad. And it's very happy to be a monad. And it's this recursive type.

[00:02:58] And so it's either this recursive type of a free monad or pure. So right off the bat, looking at the type of the function, I can just realize that if I go look up, let's go look at type of fix functor. We're gonna look at Haskell for this one.

[00:03:20] Sorry, Elle, select this one data fix. Yeah. So it's just a recursive function. And we just slap this fixed constructor on the outside each time, so that we can continue to recurse. And we actually write catamorphism that just like runs our app for us. And if I look at the free monads in Haskell, I don't know where the control free, it's a very similar thing.

[00:03:50] They brought it out into a generalized, forget it. It's the same type, though. It's got this recursive structure, they've just made monad free in interface so it's hard to see. Okay. So let's get back to our types. So I know that right off the bat, I have a type that's compatible with the free monad.

[00:04:11] But let's just stick with task right now for funsies and build out the initial stuff. I don't even know, maybe this works. Let's give it a shot. [LAUGH] We have to run our app somehow, right? So let's build a little runApp function. And the way we would run this is we would say, runApp(start) as our initial point.

[00:04:39] Now we're making a decision whether or not we wanna call these tasks or pass the continuations here. Let's go ahead and start with the continuations. I think that's a little bit more fun. I don't really know what the difference is at the moment. But we're just gonna be passing continuations instead of the actual tasks.

[00:04:54] So that way I get this function, if I call the function outcomes a task, so f().fork(console.error) or what we're gonna get is a continuation. So you can run the app with that. Well I'll pass it right into runApp. There we go. So there's a loop. So anytime anything happens, it'll fork the task and run the app again with whatever it was holding.

[00:05:22] So let's try that out node blog/index.js, of course. [LAUGH] My first step in all of this is to blow up, if you haven't noticed. [LAUGH] So it'sooking for types I got a path situation, and db. So just working in that thing itself. All right, cool. Nevermind that. So here we are asked for my name.

[00:05:56] Brian, where do you wanna go today? This is nice. CreateAuthor. That's her name, Brian. [LAUGH] All right, great. I mean, it's working. Let's write a little bit more of this thing. Let's say, let's do our write function. Well, we'll do write, all. We'll finish those two out so we can actually make a little blog post and actually let's do the latest.

[00:06:30] Let's not do all, so latest and write. So what does write looks like? Your write is gonna ask for the title, maybe, right? And then after we give it the title, we have to kinda skip to that. We have to ask it again. So I'm gonna chain, I'm wanna ask for the body.

[00:06:59] And then from there, we can chain over and we have the body. Excuse me, and then we'll have the title and the body all wrapped up. Let's put that into a constructor again composed, maybe, instead of having just creating data types on the fly in there. All right, neat.

[00:07:21] And then we just chain over that where we actually map over it cuz we will be holding the continuation. So now we have a post. I'm sorry, I forgot to save the post. Let's go ahead and save this post. So save PostTable and we're gonna pass in the post to that.

[00:07:43] And then we don't care about the post. We're just gonna go what happens after write. So latest. Okay, great, latest. Now again, I don't know if this works. I hope it works. I think it works. We have to probably make this. Let's make that. So we need a PostTable.

[00:08:02] I could just give it strings, but we're kinda wanna define some changeable table names in one spot instead of having to change them all over the place, the updates. And we ever title in our body and we'll just again just wrap it in a title and body. And I think one of our next steps after this we have some time was validate it with our fun little validation library we made.

[00:08:29] Great. But I'm more concerned about turning this thing into the best architected app, right? I don't really care so much about the little details at the moment. So latest, what does latest look like? This one's interesting. I guess we have to get all everytime. That's a little interesting.

[00:08:49] We might have to like cache the results or pass something into it. Let's look at that. We'll start by saying we'll get all(PostTable). And then I'll just get the last cuz we're cheap [LAUGH]. Posts and then I don't know. Let's just bring in randa for that [LAUGH]. Last from randa, why not?

[00:09:12] Why isn't it available to us in JavaScript? I'm not sure. Okay. We're not gonna chain, we're gonna map get the last post. And then I guess we wanna format that's for the screen in one way or another. And we're gonna go ahead and print that. All right, so it's print(formatPost) you know what?

[00:09:34] First we'll map format, then we'll map print. And actually if you wanna chain the print, cuz prints a function that will be destructive. And finally, we have to map the continuation. What happens after our latest? I guess we go back to menu. Cool. Functional programming, y'all it's no hard.

[00:09:52] [LAUGH] So let's go ahead and finish the formatPost and the print function and I think we might have a thing working. Cons formatPost. Now, this does not belong here. We're kind of in a controller, right? I don't wanna be formatting posts in the middle of my controller. I'm just gonna write it here and then we'll move it.

[00:10:18] But moving stuff is cheap. People get so into architecting their folder structures and objects and stuff. And I have a suspicion it's because they're not making anything portable. All of our stuff is portable, you just copy and paste and move it and whatever. So it's much less of an issue for us to just throw everything here and then organize it later and hindsight is 2020, right?

[00:10:42] All right, formatPost takes a post and let's just go ahead and just it's the post.title and the post.body a little. I little bit like title new line body. Cool? We cool with that, we're good? Anybody? [LAUGH] All right, last one is print. Let's make print. And that will take some string.

[00:11:14] And we're just gonna make a Task(rej, res) and res(console.log), which is nothing string. Terrific. Okay, copy that. I know, I know. There, there. Cool, so see what happens. Name? Brian. Where do you wanna go? Where do you wanna go today? How about we write. Title. Okay, First Post.

[00:11:47] Body. Hello y'all, I'm so excited, this is my blog [LAUGH]. So I'm just gonna have fun with this. Okay, and yeah, I think it works. So it asks for the title, asks for the body. And then it wrote the title and the body, the new line. It’s just hard to tell [LAUGH] what happened.

[00:12:14] So maybe we will work a little bit more on our formatting. But it’s all going. All right.