Check out a free preview of the full Introduction to Elm, v2 course:
The "Type Annotations Solution" Lesson is part of the full, Introduction to Elm, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Richard live-codes the solution to the Type Annotations exercise.

Get Unlimited Access Now

Transcript from the "Type Annotations Solution" Lesson

>> Richard Feldman: So let's go through the solutions here. So our first to do is we're gonna change the annotation for all articles to be allArticles : List Article. That's our goal here. So for that to be true we need to actually have a definition of what an article is.

[00:00:15] And to do that we're gonna say type alias Article = And that's it. So now we have defined what it is to be an article. And we've said that allArticles is a list of those, whatever that may be. To check our work, we're just gonna use elm make again.

[00:00:32] Not because we're actually gonna bring it up in the browser, just because the compiler will tell us if we made a mistake. We can confirm this by changing title to int and then recompiling. And then it's like, no, no, no, no, no. That's not what this is, and I'm going to actually highlight the offending problem in here.

[00:00:47] Title, which I claimed was an int is in fact a string. Hint: Want to convert a String into an Int? Use the String.toInt function! That is a nice hint, although this case the problem is actually just that I messed up the annotation. All right, place this comment, with a type annotation for initialModel.

[00:01:06] This one is probably the easiest one of the bunch. initialModel is a model, sure enough, okay? Next one, replace this with the type annotation for update. We saw what that one was on the slides, no surprises here. Update takes a message and a model, and returns a model.

[00:01:25] Confirm that that works, yep, it's still good. Okay. This one we wanna replace the type annotation for view. We also saw this one in the slides. Takes the model, returns HTML message. We do have our message type defined up here just like we did on the slides, description and data.

[00:01:44] Okay, here we're going to replace this one with another type annotation. But this one, view article, doesn't quite take the same argument as our other view function did. So our main primary view function which ends up calling this one, takes a model and returns HTML message, this one does not, though.

[00:02:03] This one's a little bit different, this just takes a single article. Let's confirm that. But if I try to claim that it takes a whole model, it's like, no, no, no, no, no. That's a type mismatch, this really does just take an article, not an entire model. This is pretty normal.

[00:02:19] Usually, when you're splitting up your view into multiple smaller functions that help it out or helper functions as we often refer to them. Usually, they tend to have narrower types than the functions that are calling them. You only tend to see a whole lot of view article, taking a model, which calls another function that takes a model, it's usually getting more and more specific as you break these things up.

[00:02:41] Ok, view banner is interesting because it's actually not a function and we called it view because essentially it's job is to describe some stuff. That goes into view. But, really it's just static HTML. It never changes there's nothing that it's based on so it's just not a function.

[00:02:57] It's just a plain old chunk-a-static HTML, which is totally fine, we can have that too. Confirm that everything still compiles and it did. Okay, then we have a view tag which takes two arguments, selected tag name and tag name. So both of those are strings. And here we can see something that is sorta a red flag often in Elm programs.

[00:03:22] It's not necessarily a problem that you have to fix. It's not something that you have to change. But whenever I see two arguments in a row of the same type, I know that I can mix those up and the compiler can't help me. If I were to pass the selectedTagName second accidentally and the tagName first, that would still compile because they both are strings.

[00:03:41] The function will accept them in either order, but it won't necessarily do what I want. There's a couple of different techniques to fix this. One is you can change it to be like this. You can sort of fake named arguments and say this now takes a record which has two string fields in it.

[00:04:01] And then I can essentially say in here config, and then I can say config.selectedtagname or config.tagname. Another thing I can do that's pretty conducive to this pattern is you can actually do what's called record field de-structuring. Which you can do inline anywhere. Basically, it works like this. And that is shorthand for saying, I don't actually wanna name the argument itself.

[00:04:26] I just wanna pull these fields off of it and name those. So essentially, this is saying I want to take a record. I want to extract its selected tag name field and put that in scope. I'm gonna extract its tag name field and put that in scope. Then effectively, we've ended up with the same thing as what we've had before except that now they are named by virtue of coming in as a record.

[00:04:46] Either way of doing this is totally fine. It's just a difference in how it's gonna get called, what the arguments are gonna be. One thing to note, though, is that if you do this, you've now sacrificed partial application. We can no longer partially apply these one at a time, like we could before, which depending on how we use it, may or may not be more or less useful.

[00:05:06] And that's the last of our to-dos, which means we're all good with the exercise. Any questions, yeah?
>> Speaker 2: Some of the little parts of the views, there's no onclick or anything, but you still have the message for the HTML.
>> Richard Feldman: Yes.
>> Speaker 2: Yeah.
>> Richard Feldman: That's true, so, a good observation.

[00:05:29] So, the type parameter in HTML is based on the events that it's handling. So if we don't have any onclick handlers, for example, the banner is totally non-interactive. It doesn't actually produce any events. How do we determine what this value ought to be. Short answer is that it has to agree with view if it's going to be used in view.

[00:05:51] Which is to say that this type has to be at least, if not literally HTML message, then it has to be something compatible with HTML message. We haven't really gotten to the notion of things that are compatible but not the same when it comes to types yet. We'll talk about those at the very end of the workshop the advanced workshop gets into that topic in much more detail.

[00:06:13] But for right now, I think it's enough to know that when you're getting started just make sure that they all agree and this is a pretty decent way to get them all to agree. Really, that comes up more when you're sort of trying to reuse things across applications like if you have a package, you don't necessarily wanna have the same message type for.

[00:06:30] You wanna be more flexible so that you can re-use something across projects. That's when this comes up a little bit more and there are some other circumstances. But true answer is, we're just getting started. Pretty much you can get away with just using HTML message for just about everything and you'll be all set.

[00:06:48] Good question. Follow up?
>> Speaker 2: Yeah, the other thing that maybe we're not touching on right now, if you go all the way to the bottom, just the parens there-
>> Richard Feldman: Yes, sure, yeah, that type is called unit. It's basically a really boring type that only has one value which is also called unit.

[00:07:08] And it basically means like there's nothing going on there. So program has three type parameters. One is for the model. One is for the message. And this other one in the middle here is used in the event that we're doing some JavaScript interop, which we're not doing.

[00:07:23] So there's there's nothing that goes there. So, when you see that open paren close paren, it means, hey, there's nothing of interest here, don't worry about it. And we'd see something more interesting there if we actually were doing JavaScript interop, which we are not, yet. That's the last section.