Transcript from the "Function Modeling Equivalences" Lesson
>> Let's do one more thing before we move on from function modelling. We have here a reducer. And I defined contramap where we hit the x with the f before it goes in. And we have a concat. This one's kinda interesting. This says, well, I have another reducer, right, and I have my reducer.
[00:00:23] And what I'm gonna do is I'm gonna run my accumulator an X and get a new accumulator, right? That's what this returns me, which can be the accumulator of the next reducer. So by running my reducer, with that same accumulator in value, I get a new accumulator which gets passed to the next one.
[00:00:41] So it is much more like a composition. And if we dig in a little bit deeper, let me first show how this, I wanna set this up for a second here. So I'm kind of modeling a little like Redux c style app. You don't need to know what Redux is, but it is a common architecture, and so I just wanna like walk through this for a second.
[00:01:08] So we have a login reducer, so our accumulator state, our values payload. And we're saying, if we have an email, we'll try to login. I'll check the credentials for admin and 123 and said, logged in is true or not. Otherwise we'll just return state back cuz they always have to return an accumulator.
[00:01:28] Set preferences will just if you've got preferences, we'll actually set them otherwise return state. Okay, cool, so we have two reducers. Now we're gonna do, is I'm gonna throw them in reducer kind of official function modelling reducers. So I can combine them. And then, I'm gonna run the loggedIn: false, preferences, and you've got my username and password are correct.
[00:01:53] If I run that, just save this and run it. I get logged in true, and it's at the preps, great. If I mess up the name, doesn't get logged in, while false, cool, so it's the prefs over here. All right, everybody's happy. Now, I can play around with the types here.
[00:02:13] And this is kinda getting down to the meat of why we're starting to model functions is, here we have an accumulator and an a and we return an accumulator, right? And we know that if we flip the types here, that's the same function, right? If I have both of these up front, I could just flip them around, same function.
[00:02:39] What happens if I give it one at a time? I can provide an isomorphism proof that says, I can curry and uncurry a function. So I can easily take one argument at a time. And now what's happening? What it is? Is that endo? What's endo right there? Okay, what if we turned A into endo?
[00:03:03] Okay, it's getting interesting. And what if, and this is just a function, right? I want to combine these functions. So I'll put that into a function. Now instead of a reducer, I just walked through the types I played around with equivalent types, and I've ended up at this type.
[00:03:25] That's kind of fun. [LAUGH] Let's see, and I know it's equivalent. This is a deeper subject that I'm not gonna go too deep into. But looking at playing around with argument types, moving them around, carry, uncarrying, packaging things up, kind of leads you into some of these solutions.
[00:03:46] Where you can say I have my own function, I'm gonna model it, it's gonna be great. And you write all this code and you're like, wait, that's just equivalent to this other type. [LAUGH] But I just played around with the arguments a little bit. So a lot of this is almost always kind of done for you if you kind of investigate the types.
[00:04:01] But let's go ahead, let's go right this, we already have a function and endo defined. So instead of saying, I have a login and I'm gonna concat that with this thing. I'm gonna do this right here, we'll say of a function of login. We can concat that with a function of set prefs.
[00:04:24] And we just said, we're gonna flip these around take one at a time, right? So let's do that state, payload and state. Now of course, we wanna put this into endo. And do that, as we said. And actually, this is kind of a weird API. Why don't, I just map this an endo, or sorry, you can map the function into endo, that could work.
[00:04:57] Let me see if I can get this to work first before I try that. [LAUGH] But the the idea is I can kind of push this out over here or embed it in my function definition itself. I could have put a function right here if I wanted to.
[00:05:08] These are decisions about my API, whether I wanna try to lift all these things into the right type, kind of in the background or if I wanna expose, that's how you make these functions. Okay, so now how do I work with this? Well, now state doesn't get given to it right off the bat, and a payload does.
[00:05:32] And that returns me an endo and then I'll run that with state. So we've separated these two, and still works, if I get the password wrong. Logged out false, me. Let's see if I can pull this one off and put it into an endo here. I don't wanna spend too much time on this.
[00:05:53] So I just wanted to kinda show you, this is pretty interesting stuff. So, is this work? Yeah, it works, you change the logged out false. Cool, so in my reducer combination function, I have actually mapped over the output of the function and put it in an endo, and now my function definition API's the same as it was.
[00:06:26] But I was able to change how this works. Another thing that's really interesting is if I don't need state here, we'll see this later on the day, but we can factor this out. And really, really play around with the types as we solve the functions we can kind of like magically appear new arguments out of nowhere.
[00:06:49] So we can use that as well. Modeling functions has many, many outcomes, many possibilities. Then there's a bunch of equivalent ways to model a function. So by playing around with argument types. We can discover equivalent ways to model the same function. So these function equivalences, function modeling equivalences [LAUGH] I don't know, and I think that's pretty cool.
[00:07:21] One of the reasons I think that's pretty cool is that, when we did the reducer we had these, we can do stuff like contramap and everything. And when we're starting to move these types around and change things, like maybe function doesn't have contramap and I want that so I can model it at a different way to get that and so on.
[00:07:41] It's kinda hard to get from here back to reduce was easy to kind of follow this to there, a little bit harder to go the other way.