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 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 of Null => 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, valOf, filter... • String :> STRING size, isSubstring, ^, <= ...