|
|
|
Algol & ML
Ancient Roots
Read in the book (ch.5) how Algol influenced a long chain of languages, especially.
Pascal is interesting because for many years it was initial teaching language in many
CS programs. Delphi is probably the most Pascal-like of modern industrial strength
languages.
ML (Meta-Language)
|
Read why it was created.
Inherits from the Algol tradition: basic syntactic structure, static type checking
Inherits from Lisp: strong capabilities for list processing.
ML differences
- Type Inference - program doesn't have to write most types but compiler nevertheless can do static type checking
- Powerful implementation support for recursion - tail recursion elimination
- Bias towards functional (rather than imperative) style
- Mathematically well-founded type and module systems
- Polymorphism - (parametric) one piece of code implements a function for values of many types
|
Interacting with ML System
Like scheme, ML system is fundamentally based on Read-Eval-Print loop.
- 3 + 4;
val it = 7 : int
How to think of ML
- Values bound to identifiers
- Expressions evaluated to yield values
- Each value has a type; each expression has a statically determined type
- Functions are values obtained by evaluating function expressions,
hence function expressions have statically determined type
- If else expressions
- ML does not have variables but does have ref cells
Basic types
|
bool: true false
int : 0 ~1 47
real: 7.0
unit: ()
Unit is like void in C. It is a type that contains only one value.
|
Basic value declaration
|
val <id> = expr
- val seven = 3 + 4;
val seven = 7: int
- val f = fn x => x * 3;
val f : int -> int; (int -> int implies partial function from integers to integers)
|
There is a shorthand for function declaration (just as in scheme)
which means exactly the same thing as above
Lists
[] (the empty list) also nil
[exp1, exp2,... expn] (note that all the expressions must have the same type - why?
What is the type of a list?
|
- [1, 2, 3];
val it = [1, 2, 3] : int list
-[true, true, false];
val it = [true, true, false] : bool list
|
A list can have arbitrary number of items, but all the items must have the same type.
The cons operator :: can be used to create a list. This operator appends an item
to the head of an already existing list.
|
- 1 :: [2,3];
val it = [1, 2, 3] : int list
|
Why is the notion of special form so important in Scheme and not even mentioned for ML?
What is the type for []?
Tuples
Fixed number of ordered items of possibly different types
(3, true) : int * bool
(fn x => x + 1, fn y => y * 1.0) : (int -> int) * (real -> real)
Records
Fixed number of named values of possibly different types
{left : Tree, val : int, right : Tree}
Tuples and Records have accessor functions.
Tuple is essentially a record. But you can not write
{#1=3, #2=true}
to represent
(3,true)
Datatype
datatype <id> = <constructor_clause>+
<constructor_clause> ::= <id> | <id> of <type>
More generally, a datatype may be parameterized with some type variables:
datatype <typevarlist> <id> = <id> of <type>
datatype 'a option = NONE | SOME 'a
datatype color = Red | Blue | Green
datatype 'a list = nil | :: of 'a * 'a list
where a typevarlist is either a single type variable, such as 'a, or a parenthesized
list of type variables, for example ('a, 'b, 'c).
Datatypes are one of the more powerful features of the ML languages and there
are many ways to use them.
datatype <id> = <id> of <type> | <id> of <type> | ...
datatype Address = Email of string | Phone of int | Postal of {street:string, city:string, state:string, zip:int}
The type of Address above is union. One handy union type is the option type.
Option types
datatype intOption = SOMEINT int | NOINT
These types are often used to extend a partial function of some type to a total
function with a related range type.
fun mydiv (_, 0) = NOINT
| mydiv (x, y) = SOMEINT(x div y)
It would be tedious if we had to create such a type and name the constructors for each possible base type.
Polymorphism comes to the rescue here. Data types like functions can be polymorphic.
datatype 'a Option = NONE | SOME 'a;
List-like types
We have talked about list as a built-in type. Suppose it weren't and we had to
build a list-like type by hand. In C you would have declared the list type as
|
struct listNode {
int val;
struct listNode * next;
};
typdedef struct listNode * intList;
|
In ML you define a list-like type by saying
|
datatype intList = EMPTY | cons int * intList
|
As with the option type, by using polymorphism we can write a re-usable type for lists that
works for any element type.
|
datatype 'a myList = EMPTY | cons 'a * myList
|
Implementation: Of course behind the scenes the language implementation is
doing much the same as what you do in C.
|
cons |
|
|
|
|
|
_____ |
|
_____ |
|
|
| | |
|
| |
--- |
| |
---> |
| | |
_____ |
| |
_____ |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cons |
|
|
|
|
|
_____ |
|
_____ |
|
|
| | |
|
| |
--- |
| |
---> |
| | |
_____ |
| |
_____ |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cons |
|
|
|
|
|
_____ |
|
_____ |
|
|
| | |
|
| |
--- |
| |
---> |
| | |
_____ |
| |
_____ |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
empty |
|
|
_____ |
|
| | |
|
| |
| | |
_____ |
| |
|
|
|
|
|
|
Tree types
Recursive types are also natural for trees.
datatype 'a Tree = Leaf of 'a | Interior of Tree * Tree
If you want data in the interior nodes
| Interior of 'a * Tree * Tree
If you want to name the fields
| Interior of {data:'a, left:Tree, right:Tree}
ML Book
A very nice book on ML is available on-line from Prof. Robert Harper at
Carnegie-Mellon University.
http://www-2.cs.cmu.edu/~rwh/smlbook/offline.pdf
|