Paul: Hi, there and welcome to PodRocket. I'm your host, Paul, and today we're joined with Lindsay Wardell. Welcome to the podcast, Lindsay. Lindsay Wardell: Hey, thanks for having me here. Paul: So Lindsay is an engineer at NoRedInc, and we're going to kind of be delving into Elm, the language. We're going to be talking about functional programming. We're going to be talking about what's new in Vogue in the ecosystem. Lindsay, are you like a functional person? Do you love functional programming? Is that why you're here today? Lindsay Wardell: That is what they tell me. No, I am somebody who very much enjoys functional programming. I've been on previous teams where I've tried to talk about how great it is and I'm not listened to nearly as much as I was hoping. But now I get to work on a team where everyone is using functional programming. So it feels really good. Paul: Right on. So I feel like functional programming, like you said in your talk, I think it was at Beat Con, right? It's in Vogue. It's something that's becoming very popular now, and I'm definitely curious to pick your brain about that. But I'd love to take a few minutes on the podcast, this episode, to go into the basics of functional programming, because that term gets slapped around like wet paint. And I'm wondering what does functional programming really mean, and what are some misconceptions that people have about functional programming? Because I'll step into the conversation with Haskell, right? People will say, "Oh well Haskell, it's almost, it can be considered not a real language, because there's no side effects, there's no interactions with the real world." Could we open up with that statement? What do you think about that? What's your rebuttal to that? And what are they talking about when they say there's no side effects and it has no interaction with the real world? Lindsay Wardell: I would disagree with that second statement, but it definitely very much restricts side effects, and that's one of the beautiful things about functional programming. To answer your question, I'm going to ask a different question back at you. Paul: Sure. Lindsay Wardell: So we're talking about functional programming, and first I want to talk a little bit about object-oriented programming, because that's a little more familiar to people. And if I as just somebody, not a programmer, were to ask you what is object-oriented programming? How would you describe that? Paul: How would I describe object-oriented programming? All right, let's take a stab. I would say it's a mental model where we kind of iteratively create bubbles of memory in a system that we can dynamically refer to and pass them around as needed. Lindsay Wardell: Cool. And when you went into bubbles of memory, you were very much describing objects without using the word objects? Correct? Paul: Correct. Lindsay Wardell: And that's really what it comes down to. It's for object-oriented programming, you are thinking about objects. These objects typically contain state and they contain methods, and you're just building a whole bunch of these to work together. And in functional programming, the really core piece of it is that you are writing functions. And these functions then do things that generate a state. So rather than having lots of state all over the place in different objects and different containers, typically in a functional application such as using Elm, I'm specifically talking about my experience with Elm, and later we can talk about my experience with Haskell. But in Elm you have a single state, you have the model, and whenever there is a change that goes through all of the function calls, it generates a new model. So if you're familiar with something like Redux, it's very similar to that. In that Redux you have your state, there is a mutation and then you have a new state. And that's how functional programming works. It doesn't alter the data, it just returns new state, it returns a new data. So when you're thinking about functional programming, the two big pieces that really draw people to it is that you don't have mutation and you don't have side effects. Those are going to be the two big pieces of what makes a functional programming language a functional programming language. And there is some debate around this. There's a great talk by Richard Feldman where he talks about what is functional programming. It gets down to the nitty gritty of it, and you can write functional programming even without functions is the end result of his talk, as long as you're following certain patterns. So, the main goal is you're not making mutations and you're not causing side effects. So in an object oriented world, that's what you're doing. You're making mutations and you're making side effects. That's how objects communicate, how objects update their own internal state. So introducing functional programming to an object-oriented programmer can feel like you're doing the opposite of what is reasonable at the start. But when you really get into it and you really start looking at what functional programming is and it's treated as a way to organize code, they're basically the same concept with just different applications of how you do things. Paul: That brings me back to the original statement I kind of asked you at the beginning, which is like what's the difference in the mental model? Because we're not talking about the binary being different or the run time being different, it's all about you in front of the computer with your keyboard. How are you going from path A of your idea to path B of manifesting a running file, whether that be in a compiled or scripted format? Lindsay Wardell: It's all in the head. So using a small example, if we were to create an object-oriented programming, pretend JavaScript because we like JavaScript. If you were going to write an object-oriented, a class that is a user and the user has some data like first name, last name, whatever, and it has some methods like update first name or save, things like that, you're going to write a class that contains that state and you're going to write some internal methods that are exposed to manipulate that state. And depending on how private you want this class to be, you're going to lock it down more or less. In JavaScript we typically go less. In other languages, we typically go more. And that's how you're going to approach it in object-orientated. You're going to have a file which is your class and you're going to have your data and you're going to have your methods. And in functional programming when you write that same kind of file, I'm going to use Elm's terminology. In Elm, you would write a module and we'll call the module user, it's going to have a type which will describe what that data looks like, first name, last name, email, whatever. And then you're going to have a series of functions that take that as an argument and return itself, typically. So if you want to update first name, you're going to have a function that takes a user and returns a user. And it's also going to take a first name, a string, and perform the change. But rather than mutating the data, it's just going to return a new record of the user. And so as you're organizing your code, in object- oriented, you have a single file where you have your state and you have your methods. And in functional programming you have a module where you have your type and you have your functions. It feels very similar. And once that kind of clicks in, at least this is how it worked for me, it was really easy to make the switch. Oh, if I want to write this, this is how I would do it in object-oriented, this is how I could apply it in functional. And then you can start writing your code, you can start describing what you want your application to do. And then the big differences are how that application initializes and how the global state is actually handled. And that's going to vary from language to language. Paul: Yeah, depending on the language at hand. On the topic of global state and kind of managing that top level life cycle, do you think that there is an added sort of overhead or cost to the functional paradigm mental model? Because indeed, we're talking about something that's all in the head, it's about what you're abstracting to yourself or your team. But I would wonder if we run up against some natural human limit, because people talking about, oh, psychologically we've proven no human being can have more than 200 acquaintances/friends. It's like the human brain doesn't have connections to keep track of that. And in a functional sense, if you really want to think about it as a holistic top level object itself, that person who's in charge of the project per se, really needs to understand all the possible states and inputs and outputs that could allow that module, that top level state, to interact with the real world. So do you think that there is an added overhead or an added cost that requires more training to have that bird's eye top level view from a functional point of view rather than an object oriented, which some people might find more iterative at first glance? Lindsay Wardell: I would counter with a lot of JavaScript development already has it very much in the head, because JavaScript is a dynamic and loosely typed language. So it's already common that developers have to have a mental model and maintain state in their own heads, especially in how modern applications are developed using View or React or something like that, you have to have that image of how the state is or what's interacting with what. The benefit that many functional programming languages have is how strict their type system is. So for example, Elm is strongly typed. And when I say that, what I mean is everything has a type, you cannot pass an argument to something else that is not that type, and there is no coercion. So in TypeScript, if you have an object, you can tell the TypeScript compiler that it's a string and it will listen to you. You really shouldn't do that, but you can. In Elm that isn't an option. It's just going to say, hey, you're trying to do this thing, that's a record, it's not a string, and the code just won't compile. So one of the sayings in Elm is "If it compiles, it works." Because if your Elm code compiles, you can be sure that all of the data you're passing around is actually of the type that you're expecting and you won't end up with a runtime exception, where you were thinking it's a string but it's really an object or undefined is not found on null or something like that. Paul: And on that point in Elm specifically, there is no undefined, right? Lindsay Wardell: That's correct. Paul: That's weird. Can you tell me why? Lindsay Wardell: So are you familiar with the Billion Dollar Mistake story? Paul: Let's find out, because not off the top of my head. Lindsay Wardell: Okay. So in 2009, Tony Hoare, who is the creator of Algol, described Null as the billion dollar mistake. And when he was designing that system, he added Null because it was so easy to implement. But since then it has caused a number of problems in various industries to have a Null pointer and to have data that just isn't there. And JavaScript in its infinite wisdom has two, it has Null and Undefined. So when we're working in JavaScript, we have two ways of saying there is no data here. In Elm, if you want to describe that there is nothing there, there is a type called Maybe. Maybe can either contain just a value or it contains Nothing, and it is literally just the word Nothing with a capital N, it is a type. So when you are expecting data may or may not be there, you can describe it as a Maybe, which is really helpful when you're describing your application. So rather than saying, oh, this could be Null and having to do a Null check or run down the line, I was expecting this to be a string, but it's not. You just know this is maybe something, maybe not. Paul: The point is like it's marked as that and it's not going to be a surprise at runtime because it was accounted for in the language. Lindsay Wardell: Exactly. And Elm has a handful of types like this. The other common one is Result. For example, if you need to do some sort of calculation or you're making an HTTP request as we do on the web, when that data comes back, if it's a success then you'll be in an okay state, and if you're not, you'll be in an error state. But either way it's the result type that has those two values. It's either okay or error. And then you're able to do a switch statement essentially in Elm, but would be a case statement. But that way you can get out your data and you know for sure which state you're in because you have to cover all cases. Elm doesn't let you compile if you're not covering all cases in a case statement. Paul: And that seems to be a pretty common paradigm in well-written code. Look at Rust, they have the okay or the error, you look at well done type script projects and they use TS results if they don't want to implement their own to get an okay or an error, things are accounted for and things are handled. On the topic of TypeScript and JavaScript, Lindsay's on camera with me here wearing a JavaScript shirt, and I mean like you said, let's talk about this in the lens of JavaScript because it's like the English of the programming world in today's time right now as we're doing this podcast. So maybe can we frame what Elm would look like to a JavaScript person? If somebody's in the big basket of developers and they want to check this out, what words of wisdom do you have to them going to Elm? Why should they go to Elm and is it like going from JavaScript to Rust, or is it of a lower caliber in terms of switch? Lindsay Wardell: I'd say it's a lower caliber primarily because ... So Elm, because it compiles to JavaScript and because of the way it's designed, you don't need to worry about memory, you don't need to worry about certain things that Rust has you think about like various sizes of integer. Elm doesn't think about that, because at the end of the day it does compile the JavaScript. That said, as a JavaScript developer, when you first approach Elm, your first reaction is going to be, what in the world am I looking at? There are no parentheses anywhere. Because function calls in Elm are, they look kind of like Python in that you don't have prints anywhere, or Ruby, sorry. Languages that I'm not as familiar with. You're not going to have the parentheses everywhere, you're not going to have the curly brackets everywhere for the defining scope, you just start writing code. You just say the name of the function and you put an equal sign and you go to town. So a JavaScript developer coming into Elm would also be surprised to find you're not going to need to rely on third party tooling for everything. A typical reactor view application, you're going to have the framework that you're using, you're probably going to have a third party library for state management, you're going to need a router of some sort. You probably also need Linting. You're going to need Prettier, you're going to need a whole bunch of extra stuff just to make it work. And then if you want those benefits of immutability, currently TC39 is working on an immutable object for JavaScript, but it's not done yet, so you're going to need to reach for something else and use additional libraries all over the place just to make your application work. And that's just getting to Hello World. If you're coming into Elm, if you want to write an Elm application, you just install Elm, and that's it. So you can get started with Elm just by installing the Elm language to your computer and running Elm in it. And that will initialize an Elm application. You then need to create your main dot Elm file and you need to follow a certain specification for it, but if you want to just write Hello World onto the screen, you don't need anything else. And then if you're wanting state management, well Elm's architecture is state management. You're going to get that out of the box. You don't need to worry about a framework for rendering your application because Elm just provides that, that's part of the Elm architecture as well. If you do want tooling like Lintering or Prettier for cleaning up your code, there is Elm format which follows the official spec from the Elm language. So you don't need to worry about, do I put the comma here, do I put the comma there? What's our preference here? It's just following the official guide from Elm. There is a standard for how Elm code should be formatted. If you want to use something like ES Lynch, there is Elm Review by [inaudible 00:16:13], and you can write all of your rules as needed, there are recommendations. But again, it's just following functional programming and it's just following whatever styles feel good to make your code as clean and solid as possible. You're not going to be debating, you're not going to be doing any bike shedding for example. It's more, hey, this keeps our coat clean and prevents us from leaving garbage for future developers, probably we should do that. Paul: Now, what about in the scenario that you're in a group and you have a giant turbo repo or something, and you want to write a new package and you want that to be an Elm package, what does that scenario look like? Could you write something in Elm, trans file it, and then use the resulting JavaScript in a project? Is there any way to match those ecosystems? Lindsay Wardell: Just to make sure I understand. You've got an existing JavaScript application and you want to add a little bit of Elm? Paul: That's right. Lindsay Wardell: That is very easy to do. So the way Elm renders to the DOM is very similar to something like Reactor View. Elm itself, by the way, was created in 2012. So it predates React just a little bit as far as when it's publicly released. So it follows many of the same patterns that were established during that same time period of it targets a DOM node and it takes control of that region of the DOM. So if you want to write some Elm code and render it inside of an existing React application, all you need to do is write the Elm code, compile it into JavaScript, and then import that JavaScript into your application targeted DOM node. That DOM node can be something that is controlled by React, but just let Elm do its thing in that slot and everything will work just fine. That's actually the recommended way to try out Elm and that's what NoRedInc did back in 2015, is that we're starting to explore Elm and see if it was something that they wanted to adopt. They were using React at the time and tried out Elm as a targeted experiment in one piece of their application. So they were just rendering Elm inside of React. And the experiment worked, so they kept writing more Elm code. Paul: What if I had a Node JS project? We're not doing this in the context of a DOM node. Lindsay Wardell: Elm can run on Node. That is not its strong suit. Elm is very much targeted for running in the browser, but Elm does have a way of running headless, as it were. So rather than having a view function that gets called, you're just going to be handling inputs and outputs. So yeah, you could use that in Node and it's going to follow the same pattern of you write your Elm code, you compile it to JavaScript and then you import it inside of your Node application. Elm can also work that way inside of web workers and service workers if you need it to, which is kind of fun. Paul: Especially with the whole functional worker world exploding now. I feel like it's part of every architecture I step foot into. There's a web worker somewhere. Lindsay Wardell: It's really nice to use Elm inside of a web worker because they already are following that input output pattern. Paul: Exactly. Yeah, they're functional by design. Lindsay Wardell: Exactly. Paul: Well, Lindsay, we're kind of running up on time here. I'd like to take some of the minutes at the end part here to point people to resources. When you first stepped into the Elm ecosystem, obviously the Elm docs, that's the first step. If you're trying to step into new technology, just please go read the quick start guide at a minimum. I feel like stepping into Google as your first resource could be a dangerous pitfall if it's directionless. So besides the Elm docs, are there any other places that you would point people of things you found extra insightful, useful resources? Lindsay Wardell: I think the three big resources I would point at, there is a website, Elmprogramming.com, which it describes itself as a gentle introduction to the Elm programming language. And it just walks you through all of the things that you need to know to start writing Elm. It gets you to feel out how Elm works in writing an application. If you want to go to a different source, there is Elm In Action by Richard Feldman. It's a book on manning, so manning.com. Those two resources are going to be the best if you're starting in Elm. So that's really what I would point at. And then as you get started and as you're digging into the language, I would definitely recommend the official Elm Slack. There's a lot of helpful people there, we'll call them the big names in the community, the ones that produce the big projects or doing the newsletters, stuff like that. They're always available to chat and talk about what's going on, including a large number of NoRedInc.engineers are typically there to answer questions. Paul: Those types of open public forums are usually goldmines if you run to issues like, oh, they have a discord, it's like game over. That's the best chat GPT answer you could possibly generate to ask for help. Lindsay Wardell: Absolutely. Paul: Definitely do the Slack if that's your cup of tea. Lindsay Wardell: I would also recommend if you are looking into Elm and you want to just try it out and you're familiar with just JavaScript in general, I have a template that is in the Vite Awesome Repository. It's just called Vite Elm template, and it brings all of the basic tooling together. So you have Elm Test, you have Elm Review, Elm Format, and you can just spin up a basic Elm application and just start playing with it. And the nice thing about using it with Veet, which it was kind of the point of my talk as well, besides introducing Elm to the world, is that you can integrate it nicely with any of these other frameworks. So if you're more familiar with Reactor, you're more familiar with View, you can build a viewer React application and then just inject it through Veet using just a single plugin. So rather than using two separate tooling chains, you can just stick it all through Veet, and get all of the code that you want compiled in one bundle, which is particularly helpful. So there's that template to try out. There's also an online tool called Ellie. Ellie-app.com is the website. But if you're on Google, you just look up Ellie, E-L-L-I-E. It is an online tool similar to Stack Blitz or something like that, but specifically for Elm. So you can just try out different concepts and see how it feels. And then my final resource, if you are wondering more about functional programming and just want to look into that, Richard Feldman has a number of talks on YouTube that are fantastic to look at. One I would recommend based on our starting conversation is Why Isn't Functional Programming The Norm? Richard kind of digs into how did object oriented even become popular in the first place? The TLTR on that is, it's kind of a fluke. It was almost an accident. Paul: As is some of the weird lore in the computer science, why we do things the way we do things. Is there a reason? Sometimes there's not and it was just somebody's laziness. Who knows. Yeah, so Richard Feldman, that's his name. F-E-L-D, is that how you spell the Feld? Lindsay Wardell: F-E-L-D-M-A-N. He is the head of technology at NoRedInc. And he is also the creator of the Roc programming language, R-O-C, which is currently in development. Paul: Well, Lindsay, thank you for your time and sharing your very acute expertise in the functional way of thought in paradigm. I definitely learned stuff talking to you today, and hopefully some other people can at least gather some more resources if they're already in the functional space. Lindsay Wardell: Yeah, it's my pleasure. Paul: Yeah, thanks for your time.