Introduction to ML

1 / 68

# Introduction to ML - PowerPoint PPT Presentation

Introduction to ML. You will be responsible for learning ML on your own. Today I will cover some basics Read Robert Harper’s notes on “an introduction to ML” See course webpage for pointers and info about how to get the software. Intro to ML. Highlights Functional Language

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about 'Introduction to ML' - arleen

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Introduction to ML
• You will be responsible for learning ML on your own.
• Today I will cover some basics
• Read Robert Harper’s notes on “an introduction to ML”
• See course webpage for pointers and info about how to get the software
Intro to ML
• Highlights
• Functional Language
• Functions are pervasive:
• First-class values
• Storable, arguments, results, nested
• Strongly-typed language
• Every expression has a type
• Certain errors cannot occur
• Polymorphic types provide flexibility
• Flexible Module System
• Abstract Types
• Higher-order modules (functors)
Intro to ML
• Interactive Language
• Type in expressions
• Evaluate and print type and result
• Compiler as well
• High-level programming features
• Data types
• Pattern matching
• Exceptions
• Mutable data discouraged
Preliminaries
• Read – Eval – Print – Loop

- 3 + 2;

Preliminaries
• Read – Eval – Print – Loop

- 3 + 2;

> 5: int

Preliminaries
• Read – Eval – Print – Loop

- 3 + 2;

> 5: int

- it + 7;

> 12 : int

Preliminaries
• Read – Eval – Print – Loop

- 3 + 2;

> 5: int

- it + 7;

> 12 : int

- it – 3;

> 9 : int

- 4 + true;

Type clash in : 3 + true

Looking for a : int Type

I have found a : bool Error

Preliminaries
• Read – Eval – Print – Loop

- 3 + 2;

> 5: int

- it + 7;

> 12 : int

- it – 3;

> 9 : int

- 4 + true;

Type clash in : 3 + true

Looking for a : int Type

I have found a : bool Error

- 3 div 0;

Failure : Div - run-time error

Basic Values

- ();

> () : unit => like “void” in C (sort of)

=> the uninteresting value/type

- true;

> true : bool

- false;

> false : bool

- if it then 3+2 else 7; “else” clause is always necessary

> 7 : int

- false andalso loop_Forever;

> false : bool and also, or else short-circuit eval

Basic Values

Integers

- 3 + 2

> 5 : int

- 3 + (if not true then 5 else 7);

> 10 : int No division between expressions

and statements

Strings

- “Dave” ^ “ “ ^ “Walker”;

> “Dave Walker” : string

- print “foo\n”;

foo

> 3 : int

Reals

- 3.14;

> 3.14 : real

Using SML/NJ
• Interactive mode is a good way to start learning and to debug programs, but…
• Type in a series of declarations into a “.sml” file

- use “foo.sml”

[opening foo.sml]

list of declarations

with their types

Larger Projects
• SML has its own built in interactive “make”
• Pros:
• It automatically does the dependency analysis for you
• No crazy makefile syntax to learn
• Cons:
• May be more difficult to interact with other languages or tools
Compilation Manager

sources.cm

a.sig

b.sml

c.sml

Group is

a.sig

b.sml

c.sml

• % sml
• OS.FileSys.chDir “~/courses/510/a2”;
• CM.make(); looks for “sources.cm”, analyzes dependencies
• [compiling…] compiles files in group
• [wrote…] saves binaries in ./CM/
• - CM.make’“myproj/”(); specify directory
What is next?
• ML has a rich set of structured values
• Tuples: (17, true, “stuff”)
• Records: {name = “Dave”, ssn = 332177}
• Lists: 3::4::5::nil or [3,4]@[5]
• Datatypes
• Functions
• And more!
• Rather than list all the details, we will write a couple of programs
An interpreter
• Interpreters are usually implemented as a series of transformers:

lexing/

parsing

evaluate

print

stream of

characters

abstract

syntax

abstract

value

stream of

characters

An interpreter

compilers

COS 320

US!

lexing/

parsing

evaluate

print

stream of

characters

abstract

syntax

abstract

value

stream of

characters

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)
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

-- constructors

are capitalized

-- constructors

can take a single

argument of a

particular type

type of a tuple

another eg: string * char

vertical bar

separates alternatives

LL abstract syntax in ML

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

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

If

Suc.

Bool

true

Zero

Suc.

Zero

Function declarations

function name

function parameter

fun isNumberValue t =

case t of

Zero => true

| Successor t2 => true

| _ => false

default pattern matches anything

What is the type of the parameter t? Of the function?

function name

function parameter

fun isNumberValue t =

case t of

Zero => true

| Successor t2 => true

| _ => false

default pattern matches anything

What is the type of the parameter t? Of the function?

fun isNumberValue (t:term) : bool =

case t of

Zero => true

| Successor t2 => true

| _ => false

val isNumberValue : term -> bool

ML does type inference => you need not

annotate functions yourself (but it can be helpful)

A type error

fun isNumberValue t =

case t of

Zero => 0

| Successor t2 => true

| _ => false

line 22

line 25

ex.sml:22.3-25.15 Error: types of rules don't agree [literal]

earlier rule(s): term -> int

this rule: term -> bool

in rule:

Successor t2 => true

A type error

Actually, ML will give you several errors in a row:

ex.sml:22.3-25.15 Error: types of rules don't agree [literal]

earlier rule(s): term -> int

this rule: term -> bool

in rule:

Successor t2 => true

ex.sml:22.3-25.15 Error: types of rules don't agree [literal]

earlier rule(s): term -> int

this rule: term -> bool

in rule:

_ => false

A very subtle error

fun isNumberValue t =

case t of

zero => true

| Successor t2 => true

| _ => false

The code above type checks. But when

we test it refined the function always returns “true.”

What has gone wrong?

A very subtle error

fun isNumberValue t =

case t of

zero => true

| Successor t2 => true

| _ => false

The code above type checks. But when

we 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!)

Another function

fun isNumberValue t = ...

fun isValue t =

case t of

Bool _ => true

| t => isNumberValue t

Exceptions

exception Error of string

fun debug s : unit = raise (Error s)

Exceptions

exception Error of string

fun debug s : unit = raise (Error s)

in SML interpreter:

- debug "hello";

uncaught exception Error

raised at: ex.sml:15.28-15.35

Evaluator

fun isNumberValue t = ...

fun isValue t = ...

exception NoRule

fun eval1 t =

case t of

Bool _ | Zero => raise NoRule

...

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)

...

Evaluator

exception NoRule

fun eval1 t =

case t of

Bool _ | Zero => ...

| ...

| Successor t =>

if isValue t then

raise NoRule

else

let val t’ = eval1 t in

Successor t’

end

Finishing the Evaluator

fun eval1 t =

case t of

...

| ...

| Successor t => ...

| Predecessor t => ...

| IsZero t => ...

be sure your

case is

exhaustive

Finishing the Evaluator

fun eval1 t =

case t of

...

| ...

| Successor t => ...

What if we

forgot a case?

Finishing the Evaluator

fun eval1 t =

case t of

...

| ...

| Successor t => ...

What if we

forgot a case?

ex.sml:25.2-35.12 Warning: match nonexhaustive

(Bool _ | Zero) => ...

If (Bool b,t2,t3) => ...

If (t1,t2,t3) => ...

Successor t => ...

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 very

careful

with the

syntax of

handle

(use extra

parens)

• 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 => ...)
Anonymous functions

binds a variable (n)

to a value (3)

val n = 3

val isNumberValue =

(fn t =>

case t of

zero => true

| Successor t2 => true

| _ => false)

binds a variable

(isNumberValue)

to the anonymous

function value

fn keyword

introduces

anonymous

fun

Anonymous functions

a type definition (very convenient)

type ifun = int -> int

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

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

a pair of anonymous functions

Anonymous functions

type ifun = int -> int

val intCompose : ifun * ifun -> ifun =

fn (f,g) =>

(fn x => f (g x))

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

argument is pair of functions

pattern

match

against

arg

result is a function!

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 ........

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

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

Yet another way to create a type error

fun 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)

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)

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

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 ‘

Parametric Polymorphism
• compose not : (‘c -> bool) -> (c’ -> bool)
• compose not not : bool -> bool

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

not : bool -> bool

Parametric Polymorphism
• compose (fn x => x) : ?

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

not : bool -> bool

Parametric Polymorphism
• compose (fn x => x) : ?

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

not : bool -> bool

‘d -> ‘d

Parametric Polymorphism
• compose (fn x => x) : ?

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

not : bool -> bool

must be

the same

ie:

‘a = ‘d

‘b = ‘d

‘d -> ‘d

Parametric Polymorphism
• compose (fn x => x) : ?

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

not : bool -> bool

must be

the same

ie:

‘a = ‘d

‘b = ‘d

‘d -> ‘d

Parametric Polymorphism
• compose (fn x => x) : ?

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

not : bool -> bool

‘d -> ‘d

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

Lists
• Lists:

nil : ‘a list

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

• 3 :: 4 :: 5 :: nil : int list
• (fn x => x) :: nil : (‘a -> ‘a) list
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 is

guided by the type of the argument (recall eval)

fun length l =

case l of

nil => 0

l x :: l => 1 + (length l)

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

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?

use it to write map.

ML Modules
• Signatures
• Interfaces
• Structures
• Implementations
• Functors
• Parameterized structures
• Functions from structures to structures
Structures
• structure Queue =

struct

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

exception Empty

val empty = (nil, nil)

fun insert (x, q) = …

fun remove q = …

end

Structures

structure Queue =

struct

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

exception Empty

...

end

fun insert2 q x y =

Queue.insert (y, Queue.insert (q, x))

Structures

structure Queue =

struct

...

end

structure Q = Queue

fun insert2 q x y =

Q.insert (y, Q.insert (q, x))

convenient

abbreviation

Structures

structure Queue =

struct

...

end

open Queue

fun insert2 q x y =

insert (y, insert (q, x))

for lazy

programmers

-- not encouraged!

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 components

of the structure

may be used

-- we know the

type ‘a queue

Signatures

abstract type

-- we don’t know the

type ‘a queue

signature QUEUE =

sig

type ‘a queue

exception Empty

val empty : ‘a queue

val insert : ‘a * ‘a queue -> ‘a queue

val remove : ‘a queue -> ‘a * ‘a queue

end

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

does not

type check

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

(x::y::q1,q2)

Signature Ascription
• Opaque ascription
• Provides abstract types

structure Queue :> QUEUE = …

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

structure Queue_E : QUEUE = …

• SEE Harper, chapters 18-22 for more on modules
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...
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