Check out a free preview of the full Introduction to Elm, v2 course

The "Unbound Type Variables" 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 introduces unbound type variables, which are useful because they are compatible with any other type variable.


Transcript from the "Unbound Type Variables" Lesson

>> Richard Feldman: Now another thing that we sort of have an intuition for that it ought to work without necessarily knowing how it ought to be represented is the following. So a and b is a list of strings, we also have 1.1, 2.2, that's a list of floats. What is this?

Well, it's not a list of floats or a list of strings. This sounded silly, there's no floats in it, there's no strings in it. This, the type of this is the list of a or list of vowel or a list of element, whatever you want. Point being, it's a list with an unbound type variable.

Which is just to say this is a value where it works with anything. It's a completely flexible list. If you want, you can stick a list.float together with a list of a, a lowercase a, and that'll work. You can combine, you can attach an empty list to anything you want.

Cuz it's empty, it's harmless, it, [LAUGH]. You can combine it, you can smash a million of them onto a list of floats or a list of strings and that'll totally work. Because an empty list is compatible with any other list type. So this is sort of an unbound type variable, and it means that it works anytime you expect a list with any type parameter.

You can always give it an empty list, you always give it any list that still has an unbound type parameter. So, an example of this, string.concat says give me a list of strings, and I will smash them together and give you a string. So, this is kinda like string.join, but without a joining character.

It's like give me a list of strings and I will smoosh them all together into one string. Ooh, smoosh, is that too soon? All right. That joke's not gonna work, [LAUGH] in a year. string.concat, ab and c, that'll combine those two together into abc. I can also pass string.concat empty list, even though that's not little list of strings.

If I have a list with an unbalanced type variable, I can provide that to any list, any function that accepts a list of any type. So I can, of course, say yeah, string.concat that, and it's gonna give me back empty string. That totally works even though it's not literally a list of strings, and technically string.concat says that's what it expects.

Okay, another example of this, going with moving the type variable to the other side, is String.lines. So this says given a string, I will break it on new line characters and give you back a list of all of the lines. So I can say String.lines "A\nB", and that will give me back A and B because there's one new line in between there.

Again I can pass it String.lines empty string and that will give me back an empty list. But this will not be an empty list of that is of type, oop, list a. That will actually be an empty list as a type List String. Because String.lines says, I always return a lists of string.

No matter what you give me, I will never give you back anything other than list of string. All of which is to say that, despite the fact that you have an empty list, it's not the case that there's always an unbound type variable. It depends on how you got it.

If you got it by just literally writing open square bracket, close square bracket, yes, that has an unbound type variable. Now you can still end up with an empty list that does in fact have a bound type variable, as is the case here. Okay, so we can have that in an unbound type variable with lists.

We can also have it with HTML. And this gets back to something that someone asked a question about, I think the the fourth, part four exercises. So here we have a div that says onClick Toggle. And that is an HTML message with a concrete type variable of our message type, and that's because of the onClick.

This right here is an image that has a source attribute, but it doesn't do any event handling. Because it doesn't do any event handling, technically speaking, we can annotate it like this, HTML with an unbound type variable. That's totally legit because the type variable specifies here is what type of message this thing can produce in response to user input.

But this image doesn't do anything in response to user input, which is to say yeah, it responds to no user input with means that it doesn't broadcast any message. Which means that it's compatible with any HTML that we want to use it with. Now in the course of building our application, we don't necessarily care about that because we're probably only gonna have one message type that we're dealing with at a time anyway.

But this does matter when we're reusing it. If I want to use this in one project and then publish a package where it can be used in multiple different projects, maybe one of them uses HTML string. One of them uses HTML message that looks this way, another one uses Html message that looks at it completely different way.

Anytime I have something like this image I can just drop it in anywhere and it's just totally gonna work. Now again as previously mentioned there's other tactics to working with this when you're in that situation, which we'll get into in the advanced workshop. But the point being this is an example of a list with an unbound type variable, this is an example of HTML with an unbound type variable.

And yeah, we could also call it a message with a lowercase m if we wanted to. Okay, all of which is to say this is compatible with HTML that produces that type of message. This is compatible with HTML that produces anything. And that also is, this pattern sort of continues with commands, right?

This is a command that produces messages that have a type message with a capital M. Which means that it works with update functions that accept message with the capital M. And command is a lower case m says, I don't produce any messages, which means I work with any update function.

All of this is relevant because this is what we're going to use, Cmd with a lowercase m, to talk to JavaScript. It's a command where we're going to send a value out to JavaScript, and it's gonna be fire and forget. We're gonna say here you go, JavaScript. Here is this command, here is this piece of data, bye!

And JavaScript is gonna have a callback that's gonna listen to that and grab onto it and maybe do some JavaScript stuff, maybe not. But the point is there's no callback here on the Elm site, it's not like we send off to JavaScript and then JavaScript definitely sends the message back.

This lower case m indicates that, yeah, you know what, this command can be used anywhere. It can be used across applications, whatever, because it never produces any messages.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now