24
Crash course on SML Wojciech Moczydłowski • SML – functional programming language • Complete formal semantics Extremely convenient for writing compilers, interpreters, provers and 611 homeworks • OCaml, based on SML, is practical and used in industry

Crash course on SML Wojciech Moczydłowski SML – functional programming language Complete formal semantics Extremely convenient for writing compilers, interpreters,

  • View
    223

  • Download
    1

Embed Size (px)

Citation preview

Crash course on SMLWojciech Moczydłowski

• SML – functional programming language

• Complete formal semantics

• Extremely convenient for writing compilers, interpreters, provers and 611 homeworks

• OCaml, based on SML, is practical and used in industry

SML - ideology

• 3 worlds – expressions, values and types.

• Values have types, i.e. 0 : int, “asd” : string

• Expressions have types as well, i.e. 3+4 : int, fact : int -> int

• Expressions evaluate to values

SML types

• Some types:– int, string, char– int*int, int*string– int -> int, int*int -> int– int -> int -> int– int list– ‘a list– ‘a -> ‘b -> ‘a

Interpreter

- 2+2;

val it = 4 : int

- 23+17;

val it = 40 : int

- “611 rules”;

val it = “611 rules” : string

- ~17 + 17;

val it = 0 : int

- (17, “a”);

val it = (17, “a”) : int * string

Definitions

- val i = 10;

val i = 10 : int

- val j = i + i;

val j = 20 : int

- val s = Int.toString(j);

val s = “20” : string

- val t = (i, i + 1, i + 2);

val t = (10, 11, 12) : int * int *int

- val q = #2 t;

val q = 11 : int

Datatypes

- datatype Bool = True | False

- datatype Color = Red | Black

- datatype Nat = Zero | S of Nat

- True;

val it = True : Bool

- S(S(Zero));

val it = S(S(Zero)) : Nat

Functions

• fun add(n, m : Nat) : Nat = case n of Zero => m | S(x) => S(add(x, m));• fun mult(n, m) =

case n of Zero => Zero

|S(x) => add(n, mult(x, m))• Evaluation – call by value. • All functions have one argument –

add : Nat * Nat -> Nat mult : Nat * Nat -> Nat

Anonymous functions

• As in lambda calculus, a function can be specified “on fly”

- (fn x => x + 17) 26;

val it = 43 : int;

Large parts of lambda calculus can be expressed.

Polymorphism

- val K = fn x => fn y => x;

val K = fn : ‘a -> ‘b -> ‘a

‘a ‘b are type variables.

- K 6 4;

val it = 6 : int

- K “611” 170;

val it = “611” : string

- K K K;

Polymorphism

- val I = fn x => x;

- val S = fn x => fn y => fn z =>

(x z) (y z);

- val Ap = fn f => fn x => f x;

However, the following won’t type-check:

- val Y = fn f => (fn x => f (x x)) (fn x => f (x x));

- (fn x => x x) (fn x => x x);

Datatypes reloaded

• datatype ‘a option = NONE | SOME of ‘a;

- NONE;val it = NONE : ‘a option;- SOME;val it = fn : ‘a -> ‘a option- SOME 5;val it = SOME 5 : int option;- SOME “Cornell”;val it = SOME “Cornell” : string

option;

Datatypes

- fun div(m, n) = if n = 0 then NONE else SOME (m div n);

- datatype (‘a, ‘b) Either =

Left of ‘a | Right of ‘b;

Recursive polymorphic datatypes

- datatype ‘a Tree = Null |

Node of (‘a Tree) * ‘a * (‘a Tree)

- Node (Node(Null, 5, Null), 3, Null);

- fun sum(t) = case t of

Null => 0

| Node (a, b, c) =>

sum(a) + b + sum(c)

RPD’s

fun size(t) = case t of

Null => 0

|Node(t1, _, t2) =>

size t1 + (size t2) + 1

fun add(t, n) = case t of

Null => Null

|Node(t1, m, t2) =>

Node(add(t1, n), m + n,

add(t2, n))

RPD’s

fun mul(t, n) = case t of

Null => Null

|Node(t1, m, t2) =>

Node(mul(t1, n), m * n,

mul(t2, n))

In general?

RPD’s

fun mapTree(t, f) = case t ofNull => Null

|Node(t1, m, t2) => Node(mapTree(t1, f), f m, mapTree(t2, f))

- fun add(t, n) = mapTree(t, fn m => m + n);- val mul = fn (t, n) => mapTree (t, fn m => n * m);

RPD’s

datatype ‘a list = nil | cons of

(‘a * ‘a list);

Notation:

[] denotes nil

(x::xs) denotes cons (x, xs)

Lists

Some lists:

[]

(1::(2::(3::nil)))

(“a”::”b”::”c”::nil)

Another notation:

[a, b, c] = a::b::c::nil

[1,2,3], [“a”, “b”, “c”]

Lists

- fun length(l) = case l of

[] => 0

|(x::xs) => 1 + length xs;

- fun hd [] = raise Fail “Empty”

|hd(x::xs) = x;

- fun tl [] = raise Fail “Empty”

|tl (x::xs) = xs;

Lists

- fun map(f, l) = case l of

[] => []

|(x::xs) => f x ::(map f xs);

Modules

signature SET = sig

type ‘‘a set

val empty : ‘‘a set

val insert : ‘‘a -> ‘‘a set -> ‘‘a set

val elem : ‘‘a -> ‘‘a set -> bool

end

Modules

structure Set :> SET= struct

type ’’a set = ‘‘a list

val empty : ‘‘a set = []

val insert : ‘‘a -> ‘‘a set -> ‘‘a set = fn x => fn y => x::y

val elem : ‘‘a -> ‘‘a set -> bool = ...

end

Accessing structure elements

- Set.insert, Set.add ....

- open Set;

- insert, add, ...

Standard library

• Many useful structures

• List :> LIST

hd, tl, last, map, find, filter...

• Option :> OPTION

option, isSome, val Of, filter...

• String :> STRING

size, isSubstring, ^, <= ...