One of the things I've been emphasizing is that when you learn a new language

construct you should understand precisely it's syntax,

it's type checking rules and it's evaluation rules.

And since datatype bindings and CASE expressions are

the most sophisticated language constructs we've learned in ML so far,

I thought it would be worth a short segment to just review what we've already

seen and know from a precise standpoint for each of those constructs.

Now what we'll do a little later in this section,

not in this segment,

is expand the notion of pattern matching to make it more general and more powerful.

But nothing I'm about to review with you will become untrue.

We'll just get some additional things that will also be true.

So let's start with datatype bindings.

We know the syntax.

We have an example here of datatype t

equals a bunch of constructors that types those things carry,

and they're separated by pipes.

This introduces a new type t that was not in our program before.

It also adds constructors and these constructors and parts

service functions where Ci has type t1_arrow_t,

and C2 has type t2_arrow_t.

And then in terms of using these constructors

when you have a constructor applied to a value,

that is itself a value.

In other words, values of type t both have the tag that corresponds to

the constructor as well as the value that's sort of underneath that tag.

Now that doesn't cover the case where you have a constructor that doesn't carry any data.

In that case, you just leave off the of and the type.

And in that case the constructor is not a function.

It's just already a value that has type t. So now we know how to make

expressions of type t. To access them to use their pieces we use case expressions.

And as I've emphasized this case expressions both test which

variant some value of the datatype of type t you have,

as well as give you a way to extract out the underlying data.

So let's go over a case expression again.

The syntax is here at the top of the slide.

We see that we put any expression we want between the case and the of alright and then we

have a bunch of branches each one which has

a pattern and then an arrow and then another expression.

Now this entire case expression is itself just an expression.

So we can use it anywhere we can use an expression.

I admit that it's common for a case expression to be the entire body of a function.

And I think it has been in the examples I've shown you so far.

But that's not necessary.

A case expression can appear anywhere,

and here is it's evaluation rules: You evaluate e

to a value and that thing between the case and the of that's going to give

you some value v. Now what we're going to do is we're going to pattern

match v against each of the patterns in order until we find one that matches.

So we'll check p1, if that matches we'll evaluate e one.

And that will be the answer to the whole thing.

Otherwise we try p2 and so on.

So we're only going to evaluate one of e1 through

en and which one will depend on the pattern that we find that matches.

So what that means is we have to define what it means for a pattern to match.

And so far our patterns look like constructor name,

and then one variable for each part of the thing under the constructor.

So that would match a value that was made out of the same constructor.

And then what you do when you evaluate

the corresponding expression like if p2 matches you evaluate e2,

is you evaluate e2 in an environment that is

extended so that those variables map to the corresponding pieces: X1 to V1,

X2 to V2 and so on.

And that's how we get the underlying pieces out

using the notion of variables and extending our dynamic environment.

Once again, the case where the constructor carries no data is a little bit different.

You don't have the parentheses you don't have

the variables because there is no underlying data.

So in that case if it matches then there is nothing

new to add to your environment but you still go to

the corresponding branch execute evaluate

that expression and that's the result for the entire case expression.

So that's our precise definition so far.

We're going to learn a couple of other things that will help us that are

related to pattern matching and datatypes although they're a little bit different.

See another example.

And then make pattern-matching more powerful.