Adam: Hello. This is Adam Gordon Bell. Join me as I learn about building software. This is CoRecursive.All right. I have been confused about something. I really like having static type information when I code. When I think about building something, I think about defining types, writing things to map from my one type to my other. That’s how I design in my head when I’m thinking about how to solve a problem.However, smart people, talented people that I know view things very differently. There are skilled people who would leave their job before using a language with static types. So I emailed this guy.
Jared: I’m Jared Forsyth. I am a software developer at Khan Academy.
Adam: Jared started in I was in one camp and moved to the other, sort of, because now he’s all about inferred types and maybe that’s the best of both worlds, but I’ll let him explain.
I Was Against Types
Adam: There must have been some moment where you were like, “Oh, this thing got caught.” Or “Hey, I can go to definition.” Or something where you were like, “Oh, the light bulb turns on.”
Jared: The thing that really has made it so that I never want to go back is the way that having an explicit type system changes the way you think about code and where you define explicitly this is the shape of the data that I’m going to be dealing with. Here are the data structures, I’m going to lay those out, and then I can write functions that will manipulate those.And it results in much better organized code and is just such a help in me being able to process new code that I’m reading or code that I wrote two weeks ago and I’ve forgotten entirely about.And that was kind of the, wow, this is essential because like, “Oh, it caught a bug for me. That was nice, but I’ll just not write that bug next time.”
Types Are Not A Personal Taste Thing
Adam: So I had a previous interview with DHH, created Ruby on Rails. And I think he said he doesn’t get it. He’s like, “I get some people who really want types. I don’t want them. It’s like a personal taste thing.” So you’ve made this transition. So I’m trying to figure out. There’s a thought process or a perspective that needs to change or am I just missing something? I don’t know.
Adam: It’s like the TypeScript slogan about scaling.
Adam: They’re talking about like scaling a team, actually. Not really in terms of the-
Adam: … Whatever amount of data you’re going to throw at it.
Adam: Check the number of arguments and the-
Jared: Yeah. We’re going to check the number of arguments. We’re going to do a bunch of type of checks to be like, “Okay, make sure this is a string and this is a number and this is an object that has these attributes.”That’s so much code that is… It’s defensive programming. We’ve got a better way now and it’s fantastic.
Adam: Yeah. That makes sense. If you think of that, the type checker is something just doing all that defensive stuff for you.
Adam: Yeah. What about prop types in React?
Adam: Today’s episode of CoRecursive is sponsored by Springboard. If you want to learn how to write machine learning algorithms, or if you want hands on experience deploying a machine learning model into production, or if you want to learn how to build and deploy a deep learning prototype, check out their Machine Learning Engineering Career Track.When you join this program, you’ll be paired with a machine learning expert who provides one-on-one mentorship throughout the course. This program is designed for software engineers. So you must have at least one year of experience in a modern programming language like Java or C++ or Python.Now here’s the cool part. CoRecursive is exclusively offering 20 scholarships of $500 to eligible applicants. Make sure you use code AI Springboard when you enroll. I’ll put a link in the show notes as well. The 20 scholarships are awarded on a first come first serve basis. Check it out. See if you are eligible. Applying is free and it only takes 10 minutes. Thank you, Springboard.And then where does reason come into this?
Adam: But then Reason is not OCaml strictly speaking. It’s a different language, right?
Jared: It depends on what you call a language. Is Elixir a different language from Erlang, if you’re familiar with those two?
Jared: Alexa is literally just a new syntax for Erlang. maybe I think it has a new standard library. But is Scala a different language from Java? They both run on a JVM. Scala is probably arguably more of a different language than Reason is because Reason uses the exact same compiler as OCaml does. But it is a new syntax and tool chain is often what I call it for Ocaml.
Jared: That’s right.
Adam: And then [inaudible 00:12:15] you removed everything or?
Jared: The type system is the same.
Adam: Oh, okay. Yeah.
Jared: And that’s really the bones of if you look at the OCaml compiler, the compiler itself has a number of… There’s the lexer, there’s the parser, there’s the type checker, and then there’s the thing that generates the assembly. And it’s really the only, the last bit. Generally the assembly change it while there’s a couple other internal steps. But there’s a lot that is shared and that is, I think, the things that make OCaml great. The language semantics, if you will, the module system, the function system, all of that is the same.
Jared: Right. Yeah. So literally you could go through. Initially the changes to the parser, it was based on the OCaml parser. And it was like, “Let’s just switch out. Let’s add some semi-colons here and add some parentheses here.”In the intervening years, it’s gotten further from that, but it is still based on OCaml parser and most of it is shared.
Adam: Yeah. And so we started off talking about types. So it’s the exciting bit of Reason?
Adam: Oh, so it might actually be faster than my existing JS.
Jared: Oh. So much faster.
Adam: Oh wow.
Adam: Oh wow. I wouldn’t have expected that. That’s impressive. So you mentioned laying out a data type and then using that. Do you have an example that might help us understand?
Jared: Let’s see. We could talk to do MVC. What’s your to-do item shape? It’s going to have a title. That’s going to have an author. Maybe it’s going to have a Boolean for whether it’s been completed.
Adam: Yeah. So I define a to-do item. It has some properties. And then if it were TypeScript, then my functions that dealt with that, I would just put type annotations on them.
Adam: And you’re saying, I don’t have to do that.
Adam: So can I if I want to?
Jared: Certainly. Yeah, for the purposes of reading code. Especially if you’re reading it on GitHub, it’s nice to have the annotations there because you don’t have the hover for type kind of stuff.
Adam: Nice. What else does Reason have? What else makes it unique?
Reason VS Elm
Adam: Oh, I see. Yeah. So Elm, they want it to be completely sound so then they lock it down, but it prohibits adoption to a certain extent.
Adam: How are you writing a Android app in Reason?
Jared: That’s right. Yeah. And this is taking advantage of the incredible work that’s been done in the OCaml world, where there’s an OCaml backend for Android, for iOS. So I’m not bringing in NPM libraries to my Android app, but there is a wealth of code that has just been written in pure OCaml or pure Reason. And you can just bring that in.
Adam: Interesting. It’s really exciting. I could see how it could be a limitation to in just you’re spreading yourself very thin if people are using this language to do this and sometimes it’s really great to have a certain domain where people use things and libraries build up and it gathers steam.
React With ReasonML
Adam: What’s the advantage of React and Reason? What does Reason buy you in the React ecosystem?
Adam: Did you say the React creator created Reason?
Jared: That’s right. Yeah. Jordan Walke was originator of React and helped by a bunch of other really excellent people. And then he also started the Reason project.
Adam: Oh, very cool. I’m primarily a backend developer. I do a lot of FP stuff and people use that term very generically. And I think at least in my little group, we mean something pretty specific that has to do with types and immutability and composing things. We’re trying to always convince other people that this is super useful.It’s been a new discovery to me that actually on the front end, people have been figuring this out while I wasn’t looking. I guess React, it seems to have a lot of this spirit, I guess, in it maybe.
Jared: Yes, definitely. That’s actually another good point with Reason and React because React is built very much in an FP mindset and Reason and OCaml are what you might think of as the original FP is OCaml and Haskell. Those are the things that people are drawing from these days. Unless you want untyped FP and then it’s the Lift side of things. But if you want, Reason has immutability, automatic currying of all functions and just generally functions are the way to do things as opposed to classes that encapsulate both data and functionality.
Immutability In ReasonML
Adam: You mentioned immutability. How does that work?
Jared: So Ocaml has arrays and lists. And lists are linked. So if you’re using arrays, they are immutable. And there’s certain cases where you’re writing Reason and arrays make sense. But most of the time I’m just using the default list implementation and the functional methods that go along with it.
Adam: No, that’s true.
Adam: Why would I want something to be immutable?
Jared: Immutability saves you from spooky action at a distance is generally my pitch. There’s so much uncertainty around, I’m doing this thing and I called this function and what if this function completely messes up the object that I pass to it? So I’ve got to clone the object before I hand it in or whatever. Again, defensive programming.And in a large code base where mutation is the norm, you just have to be looking over your shoulder all the time. Now, in the code bases that I work on at work, immutability is the norm. So I can generally just trust that I don’t have to be worried about somebody changes something out from under me. It would be nicer to have that statically guaranteed by the language system, but we do what we got to do.
Adam: Yeah. So it’s like, you’re working in a world where you just assume immutability. And that generally probably works, right? Because everybody has the same assumption.
Sum Types in ReasonML
Adam: Yeah. What about sum types and algebraic data types?
Adam: I didn’t know that.
Jared: … Overwrite. Oh, It’s the worst because there’s automatic follow through. And so the scope’s [inaudible 00:26:14].
Adam: I feel like we need to put an example on it.
Jared: Right, yeah.
Jared: Right. No, I mean the biggest or the most important sum type that we have in our code base that’s using Flow is our loadable data type. This is for anything we fetched from the network that we’re putting in Redux.And the naive implementation would be on your React component on state, you would have a Boolean that is whether I am loading. So there’s loading which is a Boolean and you would have error which is an optional error and then you would have data, which is optional data.And so on componentDidMount, you set loading to true and you take off the fetch and then when the fetch comes back, either you set the error to something or the data to something. And then in your render method, you have a couple of these statements. If we’re loading, then render this. Otherwise, if there’s an error, render this. Otherwise, hope you have the data and nobody messed up your state and render with the data.But having a sum type that enforces, there are three disjoint states. One of them is loading. One of them is loaded with error and one of them is loaded with data. You don’t have to worry that somebody is going to accidentally set both data and error to something. How do you render that? It’s just impossible.There’s a couple of really good talks about making impossible states unrepresentable where this doesn’t make sense to have loading be true and data be true, unless you’re refreshing, in which case let’s account for that in the data type as opposed to just some coincidence of the way you’ve set things up.
Adam: How would I pull this apart in Reason or Flow for that matter?
Jared: In Reason, you would switch on the loading state and critically, it’s impossible to get anything out of the loading state unless you switch on it. So you can’t make assumptions about you have to switch and say, is this loading or is this loaded or is this failed? And you have to handle all of those cases. I can’t tell you how many bugs in web apps are caused by someone forgetting one of the cases. Oh, I forgot that it could be loading here and it is and so everything’s dead.
Adam: It’s not just web apps. I think it’s the world.
Jared: Yeah. And so having that enforced for you, again, this is another I can offload this from my internal RAM. I don’t have to try and remember what are the cases this can be in. The compiler makes it so you can’t forget.
Adam: I think we talked about why this might be a smoother onboarding than Elm. How would you compare it to TypeScript or Flow?
TypeScript vs ReasonML vs ELM
Adam: Yeah. So how would you describe, maybe I don’t have the right words here. How would you describe that distinction?
Adam: How does that work? Because you said there’s no Any type. So what happens there?
Jared: So it is inferred to be what you think it should be. You can’t call the function two different ways.
Adam: I see.
Adam: I see. Whatever you call it as it becomes that.
Adam: Part of the allure of TypeScript, I’m less familiar with Flow, is just how easy it is. You can just rename your files and start there. What’s adoption path to get to Reason?
Adam: So have you made the transition in your day job?
Adam: Yeah. It’s a messy world out there I guess. With TypeScript, I know that somebody I was talking to was having problems just because they had a lot of stuff that took a variable number of arguments. It was perfectly acceptable to call it with one or five or whatever. And I don’t think TypeScript, I may be getting the example wrong, but it seemed like it was, yeah, I don’t know what to do with that.
Jared: Yeah. There are libraries, especially libraries written in 2010 that were like, “My favorite thing is to have a function that can be called 11 different ways with these different specific arguments.”And my response to that is that’s a bad idea. When I’m using these functions, I have to remind myself, okay, is it three arguments or is it four? The behavior changes drastically based on… That’s just not going to be easy to maintain.Now, if you mean a spread of arguments, like I want to be able to call this with the math.min() function can take any number of numbers, then I’ll just [crosstalk 00:34:44] them. That’s fine. That’s easy to type both in TypeScript and Flow.But if you’re like for some interesting reason, I want my library to only export one function when it could just as well export 10, I’m like, why are you doing that?
Adam: Yeah. Or curried functions that people have written where you can call it with one argument and then it returns a function that takes the next one, right?