CSCI 431: ML Part I

Overview of ML

Developed in Edinburgh in late 1970's as Meta-Language for automated theorem proving system.

Designed by Robin Milnor, Mike Gordon and Chris Wadsworth.

Success led to adoption and strengthening as programming language.

Important attributes:
  • Primarily applicative
  • Functions are first class values
  • Statically scoped
  • Static typing via type inference
  • Polymorphic types
  • Rich type system including support for ADT's.
  • Support for imperative features.
  • Support for exception handling
  • Automatic storage management via garbage collection
  • Incremental compiler supporting interactive program development.
  • I'm watching
    How to use the run-time system.

    Type:

    	sml

    System responds with message saying in ML, and then "-" prompt.

    Can load definitions from UNIX file by typing:

    			use ["myfile.sml"];

    where myfile.sml is the name of your file. It should be in the same directory you were in when you typed sml.

    Terminate session by typing control-D.

    Evaluate an expression by typing in and following with ";", e.g.

    - 3 + 5;

    val it = 8 : int

    "it" refers to last value computed. Can also bind value to an identifier:

    - val six = 6;

    val six = 6 : int;

    Thus typing an expression, exp, is equivalent to typing: val it = exp;

    Identifier often called a variable, but really a constant declaration ("val" for value).

    Can also define functions.

    - fun succ x = x + 1;

    val succ = fn : int -> int

    - succ 12;

    val it = 13 : int

    - 17 * (succ 3);

    val it = 68 : int;

    Can also write:

    - val succ = fn x => x + 1;

    val succ = fn : int -> int

    Note semi-colon at top-level terminates parsing and causes evaluation.

    No loops in the language, all functions written via recursion and if.. then.. else:

    - fun fact n = if n = 0 then 1 else n * fact (n-1);

    Boo!

    Data types in ML

    Built-in data types

    unit,bool, int, real, strings

    unit has only one value: ()

    bool includes true, false and operators: not, andalso, orelse

    int includes positive and negative: ...,~2, ~1,0,1,2...

    supports +,-,*,div,mod,<,<=,>,>=

    real of form 3.17, 2.4E17 with +,-,*,/,<,<=,>,>=, log, exp, sin,arctan

    string of form "my string" - \t = tab, \n = newline.

    supports ^ (concatenation), length, substring where substring("hello",1,3) -> "ell"

    Going batty

    overloading

    If expression involves an overloaded operator (e.g., + , *, -), and no other clues as to what type the argument or result should be, get type-checking error:

    - fun double x = x + x;

    Type checking error in: (syntactic context unknown)

    Unresolvable overloaded identifier: +

    Definition cannot be found for the type: ('a * 'a) -> 'a

    Boo!

    type declarations

    Can include type info if like.

    - fun succ (x:int) = x + 1;

    or

    -fun succ x : int = x + 1;

    or even

    -fun succ (x:int) : int = x + 1;

    Slimed

    Type constructors

    tuples, records, lists
    tuples
    (17,"abc", true) : int * string * bool
    records
    {name = "bob",salary = 50000.99, rank=1}: {name: string, salary:real, rank:int}

    Tuples are abbreviations of records where labels are 1,2,3,...

    Thus (17,"abc", true) = {1 = 17, 2 = "abc", 3 = true}

    Selectors: #lab : {lab : 'a,...} -> 'a

    Thus #rank({name = "bob",salary = 50000.99, rank=1}) = 1

    #2((17,"abc", true)) -> "abc"

    Ex. of function on tuples:

    - fun power (m,n):int = if n = 0 then 1

    else m * power (m,n-1);

    val power = fn : (int * int) -> int

    On the other hand

    - fun cpower m n :int = if n = 0 then 1

    else m * cpower m (n-1);

    val cpower = fn : int -> (int -> int)

    Note these are different functions!

    Latter said to be in "Curried" form (after Haskell Curry).

    Can define

    - val twopower = cpower 2

    val twopower = fn : int -> int

    - twopower 3;

    val it = 8 : int

    lists
    [2,3,4,5,6] - all elts must be of same type.

    Operations: length

    @ append - e.g. [1,2,3]@[4,5,6] = [1,2,3,4,5,6]

    :: prefix (e.g. 1::x = [1,2,3,4,5,6])

    map apply function to all elements of a list,

    e.g. map round [1.1,2.2,4.4] = [1,2,4]

    rev reverses list

    [],nil empty list

    Many kinds of lists:

    int list: [1,2,3]

    string list: ["ab","cd","ef"]

    nil is part of any list type,

    - nil;

    val it = [] : 'a list

    where 'a stands for a type variable. Similarly write:

    - map;

    val it = fn: ('a -> 'b) -> (('a list) -> ('b list))

    Map is first example of a polymorphic function.

    Lists are built up using ::, can also be decomposed the same way,

    i.e., [1,2,3] = 1::[2,3] = 1::2::[3] = 1::2::3::nil

    Can define functions by cases.

    - fun product [] : int = 1

    = | product (fst::rest) = fst * (product rest);

    Note that "=" is automatically printed on continuation line. Don't include it in your program files!

    Still watching