 Nothing else for our hosts. First of all, welcome those of you that have shown up. And this is our first talks evening in Elm Singapore Meetup Group. We have three talks lined up for you tonight. I will personally start up by talking a bit about some of the fundamentals in Elm, or the things that I think are fundamental in Elm. Then we'll have Matthew talking about Elm tests and testing in Elm. And finally, we'll diverge to Mikha, who will be talking about something that's a bit like Elm, but different in other aspects, which is PureScript, which is also an option for the front end if you are looking to use functional languages and some of the benefits that come with that. So looking very much forward to that. I don't know if anybody from ThoughtWorks are here, but thank you, ThoughtWorks, for hosting us. I think that's really great. We had our very first Meetup at ThoughtWorks in the small office across the street back in January. So this is good. Great. Let's get started if I can click the right button. So some fundamentals in Elm. My name is Matt. I kicked off this Meetup because I came from Copenhagen where I ran an Elm Meetup. And I couldn't move somewhere else and not do some Elm. And I'm really curious to meet people who are interested in this kind of stuff. I'm not a front end programmer myself. I work in back end and DevOps, actually. So I write Python a lot. But this is a great getaway from that world. So when coming to Elm from imperative languages, so JavaScript, Python, Ruby, whatever, I found that there are some things that takes a little time to get used to. It's a different way of thinking. And looking back, I can see that my thinking about those things have also changed. So initially, I thought types was one thing. And later, I learned they are also other things. And it's interesting. And what I'm going to try to do in this talk is show you around some of those areas that I found unfamiliar and give you a very short glimpse into what it looks like in Elm. And then hopefully, encourage you to go back and spend some time on these areas to improve your understanding of Elm, but also other functional languages. So the way I'd like to think of types in a very non-scientific way is that it's a way to talk about the shape of your data at runtime, but at compile time. That's where you have the talk. And the conversation you are having is with your compiler. So it forces you to think about these things. And when I'm talking about types, we have some of the basic types that we all feel comfortable with. Or no, we think we know, at least. Even if you've been doing assembly and C programming, you have some notion of these types. Another picture I have in my head is that types are like the important pieces if you're doing a jigsaw puzzle. So when you're starting a jigsaw puzzle, I usually find the interesting parts of the picture first and try to do that. So think of that as your types. That's really what I want the picture I want to give you. But in the languages we come from, types are just a standalone thing. They denote maybe the machine representation of something or simple things like these basic types are incompatible at runtime, but it won't help you until at runtime when you get the error that they are incompatible. But in languages like Elm, you can actually do more with types. You can take types and build other types from that. And in Elm, there are a couple of types that let us provide collections of types. So list is the first one that comes to mind. List is a type, and it's a type that collects types that are identical in shape. So we can have a list of floats, so we can have a list of strings, very basic stuff. There's another type that collects type in Elm. That's the tuple, which may be less familiar unless you are from Python, for example. And a tuple is a way of collecting types that are different in shape. So a little bit like a list, but with a different shape. And then you have a record. Now, a record is also a way of collecting types of different shape, but you can name them. So again, some people like to think of this a bit like an object in JavaScript or something else. But that's not what we're talking about here. Now we're talking about the shape of something. So you are denoting that these things like x, y and label belong together in some way. And I've also given them a name. Good. So from these examples, we're learning a little bit about Elm and how we represent types in Elm. And whenever you come across a single semicolon, it means something has type of. So everything to the right of the colon is the type signature. And it describes the shape of the data that we're going to put it in this thing at runtime. Types in Elm also use capitalized words, so uppercase first letter. So that's a good way to recognize them. Now, be aware, there are a couple of other things that also use capitalized words in Elm, but usually it's impossible to confuse them. At least the compiler will not get confused, but you might. Another thing you can do with types in Elm is you can give them names, another name. So you use something called type alias. And here we are giving a record of two fields with an x and a y of these types, the name point. Or we can rename string to username to be more specific about our particular usage of this type. And sometimes we just need a placeholder for a type. And placeholder does look like this. A lowercase, usually a single letter, but it can be multiple letters. But if you find anything with a lowercase, it's a placeholder for a type. In this case, I'm actually using the Elm REPL. Elm REPL is like other REPL's command line thing where you can execute some simple Elm code. Here I've just typed in an empty list, and the compiler tells me, ah, I can see it's a list, but actually I don't have any more information. So it's a list of something you haven't told me yet. We haven't agreed what's inside the list. But I'll place this a here as an indicator that something needs to go there before we have finished the conversation. So these are known as type variables, and you'll see them around, and it's one of those areas that can be a little bit confusing when you start reading larger chunks of Elm code. Now, the next fundamental thing in Elm is functions. So coming from imperative languages, at least I have a picture, I think a lot of us probably have this idea that functions, we call them methods or we call them procedures or whatever, but they are the places where we do something. So even if you're in an object or in a language, you are using these methods or functions to access some state or change some state, or maybe doing both at the same time, or we might send an HTTP request or something, but we think of it constantly as something that now something is happening, and I might look in my debug and say, yes, it's happening. But in Elm and other functional languages, functions are just a way of transforming your data at one time from one type to another, or maybe the same type, but you're making some transformation on your data, and that's basically it. They actually don't do anything. Of course, they do something, and later we'll figure out how they actually do something. But mentally, thinking about them as something that doesn't really do anything has helped me a lot in thinking about or learning Elm. So here's an example from the standard library. So you have a string length function, takes a string, and returns the length of the string. But the interesting part here for us in this scenario is that it takes a string and returns an int, so it transforms the data. And we can actually ask the REPL, we can just say, let me just execute string length, or give you that string length, and it says, hey, I can see that's a function, and it takes a string and returns an int. So the REPL is actually a nice place to be to do some of these experiments on things and learning about the types of things. You can also think of the functions as, in our jigsaw analogy, as the other pieces, so the blue sky pieces that you know, or the things that you use, the pieces you use to put together the important pieces of your puzzle. So in Elm, we define functions like this, totally straightforward, name, hello, name of the parameter, equals, and then whatever the function should be. In this case, we are saying, hello, string plus the string parameter, and that's fine. So what you need to notice, coming from some of the languages I mentioned before, is that there are no parentheses here. We don't use parentheses as a way of defining functions in the way that we do in some other languages. Calling functions is exactly the same thing. Name of the function, parameter. We've called the function, and the REPL tells us, ah, I have a string, it's a little term of type string. Now there are different ways of calling functions after each other and ensuring that parameters are passed correctly and so on. I'll just show you a couple here, so you have seen it at least. So this is not the function, parentheses, parameters in function, this is just a standard thing you learned in math in fifth grade when you had to separate the plus, you know, the addition from the multiplication in the right way. So it just groups these two things and say, execute hello on Paul and then execute string on the result of that. Elm also has the pipe operator, which is known from F-sharp if anyone was in the .NET space, and all the languages, which basically allows you to pipe the result of one function called to the next, et cetera. And you can actually also go the other way, and that may look a little strange, but in some scenarios this actually makes things more readable. So if you come across it, it just means read from the right instead. Let me see if I am getting to the end of this. So here we are. Good, yeah. So I think that can be unfamiliar, too, is this fact that functions don't have to be fully applied. I mean, you don't have to give a function all these parameters. You can do it sort of piecemeal. So for example, let's look at another standard function in the string library, string repeat. It says here that it takes int, its first parameter, and then it takes string, and then it will return a string. So what happens if we give it the first parameter in some languages, this would cause an error, right? But here it just says, all right, now I have another function, it takes a string and returns a string. And then we can give it the last parameter, and then it says, all right, now I know what to do. Here is your repeated string. It seems a little useless, maybe, when you first see it. But it's important when you look at the code and to be aware that you might not be looking at a function that has all its parameters. So you might actually be looking at a new function in a certain place in the code. And it comes very handy in things where you want to apply functions to many things. So let's say we wanted to not apply string repeat 5 to a single string, but to a whole list of strings. Then we prepare the function, say string repeat 5. And then we apply that new function to the whole list, right? So it's something to be aware of. Good. So just a small slide here on type declaration. So far we have seen so the Rappel tell us, this is of type this. You can also actively tell the compiler, I want this thing to be of a certain type. Then you put the declaration in front of your function. It's still the same syntax, colon for type has type. And then you specify the list of types that this particular function is using. And now there's another example here. And there are different good talks on how this works. But it's a way of having that conversation with the compiler. And sometimes you give it some input so that it can give you better input, right? And this is one of them. And these two talks both have some great examples of this amongst other great, at least a very good Elm talk. So you can look up the links later. All right, so that was types. And that was functions, both very fundamental to any sort of functional language, but also in Elm. Now I left one type out when I talked about the basic types in Elm. And that's the union type. It's a bit like a toggle. It's a bit like a record in the sense that it's a way of gathering data of different shape under the same reference. So you want a reference to something, but it can be different things. But there is a difference. Let's just digress and think about a scenario in the real world programming life, right? You have your program. You have some state, depending on how well if you are in sort of an imperative mode and not really modeling your thing, you might throw some Boolean flags at this. It's all right, I have a flag for authenticated or not authenticated, but I also have a username. And I'll make the agreement with myself that when the flag is authenticated, then I can look the username up in the username. So I know this, but I have no help in the language or the code to enforce this sort of connection. So I will invariably end up in some place using the username forgetting to check the authenticated, right? So once I learn that, I quickly resort to another option and say, ah, OK, I need to do something else. I need to put something in username so that I know that it's uninitialized. And I'll put a null or a none or something in there. And then I'll check both the authenticated and the user null and then I'll do something, right? But Elm has this unit type that actually combines these two things in a way that will allow the compiler to help us ensure that these states that we are talking about do not happen. So here we don't have a jigsaw analogy, but if anybody knows Uno, the card game you play with kids, there's a card in there that can be any color or any number. As long as you have it in your hand, it can be anything. But as soon as you put it on the table, you have to decide it's a red fall. Boom. Right? That's a little bit like this unit type. And when you talk about it on the compiler, it can be any of these things. But once you add runtime, it will only have a specific value or type and subtype. So let's try this out. We have a small sort of, we are doing some reporting setup for a small, what do you call it, shelter for people come when they find pets or animals. It's very small because they only take fresh fish-cats dogs and, well, something that's not an animal. So this is a way to define such a union type. But then we realize that when people come with a cat, they give them names. So how do we put that? And there's also a thing about the dogs. They can be different sizes and how much food should be given. So we can actually model that by saying, OK, I have a type here that says we can be small, medium, or big. And then we can redefine that or have a different definition of animal where it can be a fish. But when it's a cat, we also have a string representing its name. And when it's a dog, we have both a string for the name and a size of and so on. And then when we actually, and this is how we would create a dog, Hedafix, that is small, if anybody knows Hedafix. And then at runtime, we can actually look at these values. In Elm, you use the case statement for destructuring these union types in a way so you can do different things. But the interesting thing is that the dog's name is only valid here in the context of dog. You can't reference it when you have a fish, right? So and the compiler can tell you this already up front, way before you're at runtime. You're doing something wrong here if you think a fish has a name. So it will also help us cover all bases. So if you have a place where you're not, you're adding a new animal to this list, it will tell you all the places in the code where you're actually doing something with this type and say, ah, you forgot to handle reptiles, which you've just added. So a couple of small things to be aware of when you read Elm code, the compiler generates some helper functions when you define types, a little bit of syntactic sugar. So if you take this dog, which was how we instantiated the animal type before, and put it in the rebel, you'll see it's actually also a function. And it's a function that creates this kind of type. And we refer to this as a tagger. And you'll see that in many places it's a function, but has this popular name of being a tagger. Actually, records that we talked about earlier, when you define a type alias for them, they also get a helper function in the same way that can help you create this kind of type. And you'll notice when you're reading code that this is used quite a bit. And this is a case where the functions are actually uppercase or capitalized in the sense. So these are both the functions in type, and this can be a little bit confusing at the start. But once you get it, it's very straightforward. These ones, records are usually referred to as constructors. Good. An example of something that's used a lot in Elm are the error types, maybe, and result, both part of the core library. And they're both defined with this union type. Nothing mysterious about them at all. They're just a way of representing different shapes of data. Again, go see this talk by Richard Feldman. Make any possible states impossible. It's all about the union type and how to utilize that to model your data and have the combined help you. OK, let's check in a little bit. So there's another fundamental. I'm not going to talk about it. Pattern matching. Go there if you've done elixir and you know about it. It's a great thing. Study it. Good. So all these things sound fantastic, right? But I just want to make an application. How do I actually do that? It turns out that in Elm, it's actually quite easy. Because Elm is, unlike some other languages, very opinionated. It's 100% focused on making your life as a developer, mainstream developer, easy. It's focused on web application, not back end application, not something else. So it has made some decisions. And one of those decisions is to have this what is popular called the Elm architecture. But it's really, as I see it, a story about how your code interacts with the runtime. Because Elm also has a runtime that it generates. So besides compiling your code to JavaScript, it also has a runtime that it uses to run your code. And that takes some of the worries off your shoulders for when creating these applications. So jigsaw analogy, again, think of the Elm architecture as the edges of your puzzle, right? The thing that you hook everything up to. So the basic principles of the Elm architecture, it's quite simple, actually. It revolves around single source of truth. That means state lives in one place, and it's actually the runtime that holds that state for you. It will give it to you when you need it, but otherwise it has the state for you. Unidirectional data flow, which you've heard from probably other front end frameworks that try to practice this. I think React is probably one of the most known ones. But it's all about data flows one way through your programs, so you always know how that flow is. And there's no sort of side stepping. The big difference here is that in Elm, it's enforced. And the compiler helps you. So there's no sort of stepping outside the bounds. This can be maybe a little bit unnerving when you start and you come from an area where you can always just reach out for some global thing or some other or just add an event handler here. To not be able to do that, but once you get the whole idea and see all the benefits that come with it, you don't think too much about it anymore, I think. So the third part is that the rendering in the browser, using virtual DOM, as we know, from other frameworks. But Elm has its own virtual DOM renderer now. And it's quite optimized and performing quite well. And again, something that we leave to the runtime. So here we are again. I assume there's a lot of Haskell code running in the background here. So how does this actually look? So this is an event flow, blah, blah diagram. The first thing that happens, so before Elm, there is JavaScript. There's just no way around it. That's the entry point to the land of Elm. So we instantiate our Elm program. Could be something like the full screen. We have the option of passing in some initial values. And we hand it to the Elm runtime, which, and the Elm runtime immediately calls out to a function in your code, an init function, and says, here's the initial values. Please give me a model of your world, the state, the one truth, what it's called, the one. So init passes that back, plus maybe an instruction to the runtime to say, also do this for me. But basically, the runtime now hosts the state. And it immediately passes us on to a view function that I can tell the runtime to render some HTML using its virtual DOM engine. And it also has another function called subscriptions, which is part of the standard interface between the runtime and your code, saying, you know what, is there anything you want to subscribe to, any events? And it goes and does that for you. So that's it. Then things stop. Nothing more happens unless events from the outside come along, like somebody clicking on a button. Again, the cycle goes, now it doesn't call you init function because, well, we already did the init. So now there's an update. An update is the main sort of motor. But it does the same thing. The runtime gives your update function in latest state and expects you to return a new state, or the same state, if it's unchanged. And then you can also pass along these commands for the runtime. And then it goes and calls your view function, says, hey, I have a new state. Do you want to render something else? And subscriptions, hey, do you want to subscribe to something else? No, thank you. And this actually goes on. Events can come from other places. It could be that the HTTP request we fired off before is now returned. So the engine goes again, calling the update function, getting a new model, rendering the view based on this model, rendering subscriptions based on this model. And that's it. That's for you. So all you have to do in your code, written all this code, is just to attach it. Give it to the runtime. And you do that with the main function that you define. And you give it a program. And you give it a link to these four functions. And then you're just filling these functions in it. Takes the initial values, returns a model. We can read this now. Update takes type variable, type variable, and returns something else. But we can see from the names that, ah, this is the state. And this is actually a message. It's actually a tagger function that you can, oh, sorry, the instantiation of a unit, union type. So what has happened? Here's my state. Give me back a new state and any instructions for me. Subscriptions, same way. View, it returns something, a different data type than view, of course, because this is about subscriptions. But it's the same thing. It's saying, these subscriptions, oh, and when you do send me a subscription, please use these messages to alert me that I have something from this subscription. And that's what comes in up here, right? And the update function. So that's it. You've completed the whole tour. You know everything about them. Be aware there are some simpler versions of this program thing. I just wanted to show you the real one, the one that you're most likely going to use. But the others are just as valid if you don't need subscriptions or you don't need initial values. There are simple versions there. So ending here with a quote from Miles Davis about learning the basics, right? As it really spends some time on the basics, then you can forget about them and be really good at what you do, but learn the basics first, right? So that's it. Yeah, we'll leave that for later. So any questions before we go to the next talk? How will you lay out a term project? Yeah, that's always a good question. I don't think it's appropriate to answer in a very short time. And I don't have the final answer. There are different ways, but there is starting to show up some bigger projects in the open source world that you can go and get inspired from. And there are definitely people in the community that has opinions about this, right? Actually, yes, but I have a discussion on the threats. Both Eban's application, which is the creator of the language, and which are BALMA, which is also very implicated in the talk on how to structure an application in the latest L1. So in Paris, of course, yeah. Yeah, in the latest L1, it was last week. So all the videos I wanted to come out in a few days. There's something coming in the late. I mean, L is still 0.18, so it's not the magical 1.0 yet. And so there are still things coming. And the things that have been hinted about the next version is going in that direction of structure, right? Helping you build that initial structure of your application. Any other questions? No? All right? So just on that note, how stable is the language right now? It's very stable in that sense. So as in, if you learn now, it's still good. To be honest, it's hard to answer, right? Because Elm is of the form just like Python, that there is a single person that's the main driver, the benevolent dictator model. So Eban could decide to change things drastically. But he's shown us that the goals of the language are long-term. They're about catering for mainstream development. And it's about a coherent experience, right? So when people come and say, ah, can we get a change to help me with my problem? The answer will usually be maybe, but not now. Because the work that goes into ensuring that this coherence and the stability and the upgrade path, if it's a language thing, which probably be smaller things, exists for people, right? So I don't know if that completely answers your question, but that's. I'm hoping to mention some of the language that there were. It's been something like a year since 0.16, that I think 0.17, that it hasn't changed almost at all. I mean, it's mostly a few things that have appeared, but code is upwards making it possible. Just a few things have disappeared, but you have an adapter that you can run when you're in the version of the language show up. And it will update automatically almost on the code. So I think it's been something like a year that there isn't any retching chance that takes you time to adapt. And because it's targeting mainstream, we can see now that usually around conferences, people start talking about their projects. More and more larger scale companies are using it. So I think that will be taken into account. I'm not expecting much, as Matthew says, there will be some tweaks where they are optimizing the compiler, looking at things. Is anybody using this little strange feature that you can use Unicode in your code, for example? No, okay, maybe we should remove it and make things simpler. So, all right, let's get to it. In your experience, looking at L, did you have to interoperate with JavaScript code? Yes. And is it simple to interoperate? It's very well-defined, right? So in the sense that there is, one thing I should say about, one thing that's important to understand about is, Elm is opinionated, right? Elm has made some decision or even, but in the form of Elm, there's been made some decisions about what is the best way to do some things, including interrupt, and it's usually based on a safe approach, as in it's easier to add than roll back things. So Elm does not have official sort of low-level kernel FFI to JavaScript, but there's something called port, which is where you send your data in and out in a safe, type safe way. It restricts what you can send in and out, but it's flexible enough for you can do a lot of things before you actually need to resort to other. Right, so instead of sending, instead of calling the JavaScript function to add back the data, just sending data to the JavaScript function. Yeah, yeah. So you basically have a way, just like we saw with the subscriptions, right? Of saying, you know, and that instead of calling a module that knows about subscribing to WebSockets, it calls your code outside Elm and says, oh, okay, and you do whatever and you can send things back in and it will enter your update function. And treat it. So, how do we find next one here? It's different window. Yeah, it's a window that's preview. Basically, it's down to preview, yeah. Yeah. You know, what do you say? You take over and show us where it is. I will let Matthew talk. Yes.