Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction...

59
Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator for a simple language Pierce, Chapter 4 (in O’Caml) Show how to use: more functions exceptions modules
  • date post

    20-Dec-2015
  • Category

    Documents

  • view

    224
  • download

    0

Transcript of Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction...

Page 1: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Introduction to ML Last time:

Basics: integers, Booleans, tuples,... simple functions introduction to data types

This time, we continue writing an evaluator for a simple language

Pierce, Chapter 4 (in O’Caml) Show how to use:

more functions exceptions modules

Page 2: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

A little language (LL) An arithmetic expression e is

a boolean value an if statement (if e1 then e2 else e3) the number zero the successor of a number the predecessor of a number a test for zero (isZero e)

Page 3: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

LL abstract syntax in ML

datatype term = Bool of bool| If of term * term * term| Zero| Successor of term | Predecessor of term| IsZero of term

datatype declarationsgive you three things:

1. a new type

2. constructors functions for building objects of the new type

3. patterns for decomposingdatatypes

Page 4: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

LL abstract syntax in ML

If (Bool true, Zero, Successor (Successor Zero))

represents “if true then 0 else succ(succ 0)”

If

Booltrue ZeroSuc.

Suc.Zero

Page 5: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Function declarations

fun isNumberValue t = case t of Zero => true | Successor t2 => isNumberValue t2 | _ => false

function name function parameter

default pattern matches anything

Page 6: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

A very subtle error

fun isNumberValue t = case t of zero => true | Successor t2 => isNumberValue t2 | _ => false

The code above type checks. But whenwe test it refined the function always returns “true.”What has gone wrong?

Page 7: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

A very subtle error

fun isNumberValue t = case t of zero => true | Successor t2 => isNumberValue t2 | _ => false

The code above type checks. But whenwe test it refined the function always returns “true.”What has gone wrong?-- zero is not capitalized-- ML treats it like a variable pattern (matches anything!)

Page 8: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Another function

fun isNumberValue t = ...

fun isValue t = case t of Bool _ => true | t => isNumberValue t

Page 9: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Exceptions

exception Error of string

fun debug s : unit = raise (Error s)

Page 10: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Exceptions

exception Error of string

fun debug s : unit = raise (Error s)

- debug "hello";

uncaught exception Error raised at: ex.sml:15.28-15.35

in SML interpreter:

Page 11: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Evaluator

fun isNumberValue t = ...fun isValue t = ...

exception NoRule

fun eval1 t = case t of Bool _ | Zero => raise NoRule...

Page 12: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Evaluator

...

fun eval1 t = case t of Bool _ | Zero => raise NoRule | If(Bool b,t2,t3) => (if b then t2 else t3) | If(t1,t2,t3) => If (eval1 t1,t2,t3) ...

Page 13: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Evaluatorexception NoRule

fun eval1 t = case t of ... | Successor t => if isValue t then raise NoRule else let val t’ = eval1 t in Successor t’ end

let expression:

let declarationsin expressionend

Page 14: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Finishing the Evaluatorfun eval1 t = case t of ... | ... | Successor t => ... | Predecessor t => ... | IsZero t => ...

be sure yourcase isexhaustive

Page 15: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Finishing the Evaluatorfun eval1 t = case t of ... | ... | Successor t => ... What if we

forgot a case?

Page 16: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Finishing the Evaluator

ex.sml:25.2-35.12 Warning: match nonexhaustive (Bool _ | Zero) => ... If (Bool b,t2,t3) => ... If (t1,t2,t3) => ... Successor t => ...

fun eval1 t = case t of ... | ... | Successor t => ... What if we

forgot a case?

Page 17: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Multi-step evaluation

fun eval1 t = ...

fun eval t = let fun loop t = loop (eval1 t) val message = “Done\n” in ((loop t) handle NoRule => print message | Error s => print s) end

Be verycarefulwith thesyntax ofhandle(use extra parens)

Page 18: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Done with the evaluator

Page 19: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

ML is all about functions There are many different ways to

define functions! I almost always use “fun f x = ...” When I am only going to use a

function once and it is not recursive, I write an anonymous function: (fn x => ...)

Page 20: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Anonymous functions

val n = 3

val isValue = (fn t => case t of Bool _ => true | t => isNumberValue t)

binds a variable (n)to a value (3)

binds a variable(isValue)

to the anonymous function valuefn keyword

introducesanonymousfun

Page 21: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Anonymous functions

type ifun = int -> int

val intCompose : ifun * ifun -> ifun = ...

fun add3 x = intCompose ((fn x => x + 2), (fn y => y + 1)) x

a pair of anonymous functions

a type definition (very convenient)

Page 22: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Anonymous functions

type ifun = int -> int

val intCompose : ifun * ifun -> ifun = fn (f,g) => (fn x => f (g x))

fun add3 x = intCompose ((fn x => x + 2), (fn y => y + 1)) x

result is a function!

argument is pair of functionspatternmatchagainstarg

Page 23: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Another way to write a function

fun f x = ........

can be written as:

val f = (fn x => ......)

provided the function is not recursive;f does not appear in ........

Page 24: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Another way to write a function

fun f x = ....

can always be written as:

val rec f = (fn x => ...f can be used here...)

keyword rec declares a recursive function value

Page 25: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Yet another way to write a function

fun isNumberValue Zero = true | isNumberValue (Successor t2) = true | isNumberValue (_) = true

This is just an abbreviation for

fun isNumberValue t = case t of Zero => true | Successor t2 => true | _ => true

Page 26: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Yet another way to create a type errorfun isNumberValue 0 = true | isNumberValue (Successor t2) = true | isNumberValue (_) = true

ex.sml:9.1-11.29 Error: parameter or result constraints of clauses don't agree [literal] this clause: term -> 'Z previous clauses: int -> 'Z in declaration: isNumberValue = (fn 0 => true | Successor t2 => true | _ => true)

Page 27: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism Functions like compose work on objects

of many different types

val compose = fn f => fn g => fn x => f (g x)

compose (fn x => x + 1) (fn x => x + 2)

compose not (fn x => x < 17)

Page 28: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism Functions like compose work on objects

of many different types

val compose = fn f => fn g => fn x => f (g x)

compose not (fn x => x < 17)

compose (fn x => x < 17) not BAD!!

Page 29: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism Functions like compose work on objects

of many different types

val compose = fn f => fn g => fn x => f (g x)

compose: (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)

Note: type variables are written with ‘

a type variablestands forany type

Page 30: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism Functions like compose work on objects

of many different types

compose: (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)

compose: (int -> ‘b) -> (‘c -> int) -> (‘c -> ‘b)

can be used as if it had the type:

Page 31: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism Functions like compose work on objects

of many different types

compose: (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)

compose: ((int * int) -> ‘b) -> (‘c -> (int * int)) -> (‘c -> ‘b)

can be used as if it had the type:

Page 32: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism Functions like compose work on objects

of many different types

compose: (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)

compose: (unit -> int) -> (int -> unit) -> (int -> int)

can be used as if it had the type:

Page 33: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose not : ??

compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)not : bool -> bool

Page 34: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose not : ??

compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)not : bool -> bool

type of compose’s argument must equalthe type of not:bool -> bool == (‘a -> ‘b)

Page 35: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose not : ??

compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)not : bool -> bool

‘a must be bool‘b must be bool as well(in this use of compose)

therefore:

Page 36: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose not : (‘c -> bool) -> (c’ -> bool)

compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)not : bool -> bool

‘a = bool‘b = bool

Page 37: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose not : (‘c -> bool) -> (c’ -> bool)

(compose not) not : bool -> bool

compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)not : bool -> bool

Page 38: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose not : (‘c -> bool) -> (c’ -> bool)

(compose not) not : ??

compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)not : bool -> bool

Page 39: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose (fn x => x) : ?

compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)

Page 40: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose (fn x => x) : ?

compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)

‘d -> ‘d

Page 41: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose (fn x => x) : ?

compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b)

‘d -> ‘d

must be the same

ie:

‘a = ‘d‘b = ‘d

Page 42: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose (fn x => x) : ?

compose : (‘d -> ‘d) -> (‘c -> ‘d) -> (‘c -> ‘d)

‘d -> ‘d

must be the same

ie:

‘a = ‘d‘b = ‘d

Page 43: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Parametric Polymorphism

compose (fn x => x) : ?

compose : (‘d -> ‘d) -> (‘c -> ‘d) -> (‘c -> ‘d)

‘d -> ‘d

(‘c -> ‘d) -> (‘c -> ‘d)

Page 44: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Lists Lists:

nil : ‘a list

:: : ‘a * ‘a list -> ‘a list

3 :: 4 :: 5 :: nil : int list

(fn x => x) :: nil : (‘a -> ‘a) list

Page 45: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Lists Lists:

[] : ‘a list

3 :: [4, 5] : int list

[fn x => x] : (‘a -> ‘a) list

a different wayof writing “nil”

Page 46: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

List Processing

Functions over lists are usually defined by case analysis (induction) over the structure of a list

Hint: often, the structure of a function isguided by the type of the argument (recall eval)

fun length l = case l of nil => 0 l _ :: l => 1 + (length l)

Page 47: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

List Processing

fun map f l = case l of nil => [] l x :: l => (f x) :: (map f l)

an incredibly useful function:

- map (fn x => x+1) [1,2,3]; > val it = [2,3,4] ; int list

Page 48: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

List Processing

fun fold f a l = case l of nil => a l x :: l => f (fold f a l) x

another incredibly useful function

what does it do? what is its type?use it to write map.

Page 49: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

ML Modules Signatures

Interfaces Structures

Implementations Functors

Parameterized structures Functions from structures to

structures

Page 50: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Structures

structure Queue = struct

type ‘a queue = ‘a list * ‘a listexception Emptyval empty = (nil, nil)fun insert (x, q) = …fun remove q = …

end

Page 51: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Structures

structure Queue = struct

type ‘a queue = ‘a list * ‘a listexception Empty

...end

fun insert2 q x y = Queue.insert (y, Queue.insert (q, x))

Page 52: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Structures

structure Queue = struct

...end

structure Q = Queue

fun insert2 q x y = Q.insert (y, Q.insert (q, x))

convenientabbreviation

Page 53: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Structures

structure Queue = struct

...end

open Queue

fun insert2 q x y = insert (y, insert (q, x))

for lazy programmers

-- not encouraged!

Page 54: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Structures

structure Queue = struct

type ‘a queue = ‘a list * ‘a list...

end

fun insert2 (q1,q2) x y : ‘a queue = (x::y::q1,q2)

by default,all componentsof the structure may be used

-- we know the type ‘a queue

Page 55: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Signatures

signature QUEUE =sig

type ‘a queueexception Emptyval empty : ‘a queueval insert : ‘a * ‘a queue -> ‘a queueval remove : ‘a queue -> ‘a * ‘a

queue end

abstract type

-- we don’t know the type ‘a queue

Page 56: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Information hiding

signature QUEUE = sig type ‘a queue ... end

structure Queue :> QUEUE = struct type ‘a queue = ‘a list * ‘a list val empty = (nil, nil) … end

fun insert2 (q1,q2) x y : ‘a queue = (x::y::q1,q2)

does nottype check

Page 57: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Signature Ascription Opaque ascription

Provides abstract typesstructure Queue :> QUEUE = …

Transparent ascription A special case of opaque ascription Hides fields but does not make types

abstractstructure Queue_E : QUEUE = …

SEE Harper, chapters 18-22 for more on modules

Page 58: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Other things functors (functions from structures

to structures) references (mutable data structures)

ref e; !e; e1 := e2 while loops, for loops arrays (* comments (* can be *) nested *) a bunch of other stuff...

Page 59: Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.

Last Things Learning to program in SML can be

tricky at first But once you get used to it, you

will never want to go back to imperative languages

Check out the reference materials listed on the course homepage