cse321, programming languages and compilers 1 6/21/2015 standard ml in this course we will use an...
Post on 20-Dec-2015
215 views
TRANSCRIPT
Cse321, Programming Languages and Compilers
104/18/23
Standard ML• In this course we will use an
implementation of the language Standard ML
• Notes by Riccardo Pucella, about programming in ML • http://www.cs.cornell.edu/riccardo/smlnj.html
• The SML/NJ Homepage has lots of useful information: http://www.smlnj.org//
• You can get a version to install on your own machine there.
I will use the version 110.57 of SML. Earlier versions probably will work as well. I don’t foresee any problems with other versions, but if you want to use the identical version that I use in class then this is the one.
Cse321, Programming Languages and Compilers
204/18/23
Characteristics of SML
• Applicative style – input output description of problem.
• First class functions – pass as parameters
– return as value of a function
– store in data-structures
• Less Importantly:– Automatic memory management (G.C. no new or malloc)
– Use of a strong type system which uses type inference, i.e. no declarations but still strongly typed.
Cse321, Programming Languages and Compilers
304/18/23
Syntactic Elements
• Identifiers start with a letter followed by digits or other letters or primes or underscores.– Valid Examples: a a3 a’b aF
– Invalid Examples: 12A
• Identifiers can also be constructed with a sequence of operators like: !@#$%^&*+~
• Reserved words include– fun val datatype if then else– if of let in end type
Cse321, Programming Languages and Compilers
404/18/23
Interacting
• The normal style for interaction is to start SML, and then type definitions into the window.
• Types of commands– 4 + 5;– val x = 34;– fun f x = x + 1;
• Here are two commands you might find useful.
val pwd = OS.FileSys.getDir;val cd = OS.FileSys.chDir;
• To load a file that has a sml program type
Use “file.sml”;
Cse321, Programming Languages and Compilers
504/18/23
The SML Read-Typecheck-Eval-Print Loop
Standard ML of New Jersey v110.57 [built: Mon Nov 21 21:46:28 2005]-- 3+5;val it = 8 : int-- print "Hi there\n";Hi thereval it = () : unit-- val x = 22;val x = 22 : int-- x+ 5;val it = 27 : int--val pwd = OS.FileSys.getDir;-val pwd = fn : unit -> string
- val cd = OS.FileSys.chDir;val cd = fn : string -> unit-
Note the semicolon when you’re ready to evaluate.
Otherwise commands can spread across several
lines.
Cse321, Programming Languages and Compilers
604/18/23
Evaluation vs. Declaration evaluation- 5;val it = 5 : int- 3+4;val it = 7 : int
declaration- val it = 7 : int- val tim = 5 : int
evaluation- tim + 7;val it = 12 : int
declaration- fun plusone x = x + 1;val plusone = fn : int -> int
Cse321, Programming Languages and Compilers
704/18/23
Bindings and environments, and scope:val x = 12;fun f x = x + 2;fun g y = x + 2;
• fun bindings are just like val bindings
val f = (fn x => x + 2);
• But NOT RECURSIVE PROGRAMS! why?
fun plus x y = if x = 0 then y else 1 + (plus (x-1) y); val rec plus = fn x => fn y => if x = 0 then y else 1 + (plus (x-1) y);
Cse321, Programming Languages and Compilers
804/18/23
Functions• Functions are usually defined in Files and
loaded into to SML. Example:– use “lect01.sml”
• Functions on numbers– Type of numbers: Int and Real
– Conversion functions: floor, ceiling, trunc, round
• Functions on Booleans– Relational operators
< > <= >= == !=
– Combinators
andalso orelse
• Examples- 5 > 7
false
- 1==4
false
Cse321, Programming Languages and Compilers
904/18/23
Finding type of functions- length
val it = fn : 'a list -> int
-
- op @;
val it = fn : 'a list * 'a list -> 'a list
-
- rev;
val it = fn : 'a list -> 'a list
-
- op +;
val it = fn : int * int -> int
Cse321, Programming Languages and Compilers
1004/18/23
Functions• Defined by writing equations (sometimes more than
1)• By Declaration: fun plusone x = x+1;
• By Lambda expression: fn x => x + 1– These are anonymous functions, and are probably new to you. Don’t let
them scare you.
• Application by juxtaposition (no parenthesis needed)• plusone 8 • (fn x => x + 1) 8
• Functions of more than 1 argument:• tuples• currying
Cse321, Programming Languages and Compilers
1104/18/23
Multi Argument functions: Tuples
• fun evenprod (x,y) = even(x * y);
• Conditional Expressions: If
• fun minpair (x,y) = if x < y then x else y;
Cse321, Programming Languages and Compilers
1204/18/23
Multi Argument functions: By Currying
fun f a b c = a + b + c + 1;
• has type
val f = fn : int -> int -> int -> int
• READ AS: int -> (int -> (int -> int))
• Be sure you understand the difference between the two styles.
• fun evenprod (x,y) = even(x * y);– (int * int) -> bool
• fun evenprod’ x y = even(x * y);– int -> int -> bool
Cse321, Programming Languages and Compilers
1304/18/23
Pattern Matching Definitions:
fun and true false = false
| and true true = true
| and false false = false
| and false true = false;
• (ORDER MATTERS)
• Variables in Patterns:
fun and true true = true
| and x y = false
Note that “and” has more than
1 equation.
Cse321, Programming Languages and Compilers
1404/18/23
Rules for patterns:
• Patterns has only Constructors, (true, false, :: ) variables (x, y, z) , and constants (3, “red”).
• All the patterns (on the left) should have
compatible types
• The cases should be exhaustive
• There should be no ambiguity as to which case applies. (Ordering fixes ambiguity if there is any)
Cse321, Programming Languages and Compilers
1504/18/23
Lists in ML
• Constant lists
• [3,6,8]
• ["red", "yellow", ""]
• []
Cse321, Programming Languages and Compilers
1604/18/23
Construction of lists
• The Empty List
[]
• The "Cons" (op :: ) Constructor
4::[3,7];
val it = [4,3,7] : int list
• Concatenation
[3,4] @ [6,7,8]
val it = [3,4,6,7,8] : int list
Cse321, Programming Languages and Compilers
1704/18/23
Taking Lists Apart? hd [1,2,3]
1
? tl [1,2,3]
[2, 3]
? List.take (2,[1,2,3])
[1,2]
? List.drop (2,[1,2,3])
[3]
Cse321, Programming Languages and Compilers
1804/18/23
Libraries
• There are lots of predefined types and functions in SML when it starts up.
• You can find out about them at:http://www.smlnj.org//basis/pages/top-level-chapter.html
• Many more can be found in the other libraries.– http://www.standardml.org/Basis/manpages.html
• Libraries are encapsulated in Structures which are classified by Signatures (a list of what is in the structure).
Cse321, Programming Languages and Compilers
1904/18/23
Peeking inside a Structure
• To see what is inside a Structure you can open it.
• This is somewhat of a hack, but it is useful.Standard ML of New Jersey v110.57 [built: Mon Nov 21 21:46:28 2005]- signature S = INTEGER;signature INTEGER = sig eqtype int val precision : Int31.int option val minInt : int option val maxInt : int option val ~ : int -> int val + : int * int -> int val - : int * int -> int val * : int * int -> int val div : int * int -> int val mod : int * int -> int val quot : int * int -> int val rem : int * int -> int . . .end
Cse321, Programming Languages and Compilers
2004/18/23
fun lastone x = hd (rev x)fun prefix x = rev (tl (rev x))
In Class Exercise 1• Define prefix and lastone in terms of head tail and reverse.
• First make a file “S01code.sml”• Start sml• Change directory to where the file resides• Load the file ( use “S01code.sml” )• Test the function
Standard ML of New Jersey v110.57 - K;- val cd = OS.FileSys.chDir;val cd = fn : string -> unit- cd "D:/work/sheard/courses/PsuCs321/web/notes";- use "S01code.sml";[opening S01code.sml]val lastone = fn : 'a list -> 'aval prefix = fn : 'a list -> 'a listval it = () : unit- lastone [1,2,3,4];val it = 4 : int
Cse321, Programming Languages and Compilers
2104/18/23
In Class Exercise 2• define map and filter functions
– mymap f [1,2,3] = [f 1, f 2, f 3]– filter even [1,2,3,4,5] = [2,4]
fun mymap f [] = []
| mymap f (x::xs) = (f x)::(mymap f xs);
fun filter p [] = []
| filter p (x::xs) =
if (p x) then x::(filter p xs) else (filter p xs);
• Sample Session
- mymap plusone [2,3,4]
[3, 4, 5]
- myfilter even [1,2,3,4,5,6]
[2, 4, 6]
Cse321, Programming Languages and Compilers
2204/18/23
Case expressions
val ex1 =
case [1,2,3] of
[] => 0
| (1::xs) => if null xs
then 1
else 2
| (x::xs) => 3;
Clauses separated
by “|”
Keyword of
Clauses can span multiple
lines
The semicolon ends the “val ex1 = ” declaration not the
case exp.
Cse321, Programming Languages and Compilers
2304/18/23
Using case in fun definition• The case expression uses patterns
fun length(y) =
case y of
[] => 0
| (x :: xs) => 1 + (length xs)
• In the pattern: (x :: xs)– x, stands for the hd(y)
– xs, stands for the tl(y)
Cse321, Programming Languages and Compilers
2404/18/23
More about patterns• Patterns can be nested• Patterns can have wild-cards
fun double y =
case y of
(a :: (b :: [])) => true
| _ => false
• Special syntax for list Patterns
fun exactlytwo x =
Case x of
[] => false
| [x] => false
| [x,y] => true
| (x:xs) => false;
These features can be used in “fun”
declarations with multiple clauses as
well as in “case” expressions!
Cse321, Programming Languages and Compilers
2504/18/23
Let expressions
• Let expressions allow programmers to make local declaration for both values and functions.
val ex2 =
let val x = 34
fun f x = x - 3
in f x - 4 end;
Multiple declarations allowed, both “val” and
“fun”, no separators necessary
The scope of the new declarations is the
expression between the key words “in” and “end”
Cse321, Programming Languages and Compilers
2604/18/23
Exceptions
exception Error of string;
fun error s = raise (Error s);
fun ex3 b =
(if b then error "true branch"
else "false branch")
handle Error message => message
| other => raise other;
A new exception is declared, it carries a string as error information. Exceptions
can carry any kind of data.
Exceptions can be raised, to short-circuit normal
evaluation.
Main computation
returns a string
Handler also returns a stringA handler, like a “case” has multiple clauses, each can
handle a different kind of error. Note “|” separating clauses.
Keyword handle
Cse321, Programming Languages and Compilers
2704/18/23
Syntax of “case” vs “handle”• “case” is before the computation being
analyzed
case (revonto (g x) 4) of
[] => true
| (x:xs) => false
• “handle” is after the computation that might fail
(compute (g y) (length zs))
handle Error s => g s
| BadLevel n => n+1
| other => raise other
Cse321, Programming Languages and Compilers
2804/18/23
Review
• Case, let, and exceptions are rich constructs in ML.
• Case allows pattern matching without defining a new function.
• Let allows us to introduce local bindings. It allows us to introduce more than 1 binding.
• Exceptions allow non-standard control. The key operations on exceptions are “raise” and “handle”– Handle is like a “case” in that it can have several clause, separated
by “|”, the first that matches “wins”
Cse321, Programming Languages and Compilers
2904/18/23
Introducing new kinds of data• Objects of an inductive type are allocated in
the heap.
• The abstract interface is to use constructor (functions) rather than malloc
• This provides some level of type checking, and abstraction.
• Constructor functions automatically defined. No need to define like constructors in Java
• Two kinds of constructors. Constants like nil ([]), and functions like cons (::).
Cse321, Programming Languages and Compilers
3004/18/23
Constant Constructors• Constant constructors are constant
• Can be allocated once at compile-time.
• Like constant pointers that never change.
• The nil constructor [] for lists is an example.
Cse321, Programming Languages and Compilers
3104/18/23
Constructor Functions• Constructor functions allocate in the heap.• Each constructor may allocate a different
amount of memory• If we had to do this in C we might write
list cons (void * hd, list tl){ list Block = (list) malloc (sizeof (struct listStruct)); Block->Tag = consTag; Block->Data.consData.hd = hd; Block->Data.consData.tl = tl; return (Block);};
• In ML this is done automatically.
Cse321, Programming Languages and Compilers
3204/18/23
Introducing new data and constructors
datatype Tree = Tip | Node of Tree * int * Tree;
val tree1 = Node(Node(Tip,4,Tip) ,7 ,Node(Tip,10,Tip));
Constant constructor, contains no data
Constructor function. Contains 3 fields. The function Node takes a triple with 3
components. The “of” keyword is used for constructor functions
7
4 10
Cse321, Programming Languages and Compilers
3304/18/23
Pattern Matching functions
fun sum Tip = 0
| sum (Node(x,n,y)) = n + sum x + sum y;
• using binary search tree invariant
fun search n Tip = false
| search n (Node(x,m,y)) =
if n=m
then true
else if (n < m) then search n x
else search n y;
Two constructors, two clauses
The bar “|” separates clauses
Cse321, Programming Languages and Compilers
3404/18/23
Searching Trees.fun search n Tip = false
| search n (Node(x,m,y)) =
if n=m then true
else if (n < m) then search n x else search n y;
• val ex4 = search 3 tree1;• search 3 (Node(Node(Tip,4,Tip),7,Node(Tip,10,Tip)))• search 3 (Node (Tip,4,Tip))• search 3 Tip• false
• val ex5 = search 10 tree1;• search 10 (Node(Node(Tip,4,Tip),7,Node(Tip,10,Tip)))• search 10 (Node (Tip,10,Tip))• true
Cse321, Programming Languages and Compilers
3504/18/23
Expressions
datatype Exp
= Const of int
| Add of Exp * Exp
| Mult of Exp * Exp
| Sub of Exp * Exp;
val exp1 = Add(Const 4,Const 3); (* 4+3 *)
val exp2 = Mult(exp1,exp1); (* (4+3)*(4+3) *)
Mult(Add(Const 4,Const 3)
, Add(Const 4,Const 3));
Cse321, Programming Languages and Compilers
3604/18/23
Pattern matching functions
fun ExpValue (Const n) = n
| ExpValue (Add(x,y))
= ExpValue x + ExpValue y
| ExpValue (Mult(x,y))
= ExpValue x * ExpValue y
| ExpValue (Sub(x,y))
= ExpValue x - ExpValue y;
Cse321, Programming Languages and Compilers
3704/18/23
More SML
• In SML we use library functions all the time.– Int.toString– List.exists
• The list library functions are particularly useful.– These library functions often take a function as an argument– List.map : ('a -> 'b) -> 'a list -> 'b list– List.find : ('a -> bool) -> 'a list -> 'a option– List.filter : ('a -> bool) -> 'a list -> 'a list– List.exists : ('a -> bool) -> 'a list -> bool– List.all : ('a -> bool) -> 'a list -> bool– List.foldr : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
• It is worth studying these functions closely
Cse321, Programming Languages and Compilers
3804/18/23
List.map captures a pattern
• Add one to every element of a list– fun addone [] = []– | addone (x::xs) = (x + 1) :: addone xs
addone [2,3,4] val it = [3,4,5] : int list
• Turn a list of ints into a list of strings– fun stringy [] = []– | stringy (x::xs) = (Int.toString x) :: stringy xs
stringy [2,5,9] val it = ["2","5","9"]:string list
• Negate every element of a list– fun negL [] = []– | negL (x::xs) = (not x) :: negL xs
negL [true,3 > 4] val it = [false,true] : bool list
Cse321, Programming Languages and Compilers
3904/18/23
Patternfun addone [] = [] | addone (x::xs) = (x + 1) :: addone xsfun stringy [] = [] | stringy (x::xs) = (Int.toString x) :: stringy xsfun negL [] = [] | negL (x::xs) = (not x) :: negL xs
fun map f [] = [] | map f (x::xs) = (f x) :: (map f xs)
val ex1 = map (fn x => (x+1)) [2,3,4];val ex1 = [3,4,5] : int list
val ex2 = map Int.toString [2,5,7];val ex2 = ["2","5","7"] : string list
val ex3 = map not [true, 3 > 4];val ex3 = [false,true] : bool list
Cse321, Programming Languages and Compilers
4004/18/23
Anonymous functions• Study: (fn x => (x+1))
– It is an anonymous function. A function without a name.– It has one parameter “x”– It adds one to its parameter, and returns the result.
(fn x => (x+1)) 4;val it = 5 : int
• Any non-recursive function can be written anonymously.– (fn x => x = 5)
» Tests if its parameter is equal to 5map (fn x => x=5) [1,4,5,3,5];val it = [false,false,true,false,true] : bool list
– (fn x => fn y => (x,y))» Has two parameters» Returns a pair
– (fn (x,y) => (not y, x+3))» What is the type of this function?
Cse321, Programming Languages and Compilers
4104/18/23
List.find
• Used for searching a list.– List.find : ('a -> bool) -> 'a list -> 'a option
• Uses a function as a parameter to determine if the search is successful.
• E.g. Is there an even element in a list?List.find even [1,3,5];
val it = NONE : int option
List.find even [1,3,4];
val it = SOME 4 : int option
Cse321, Programming Languages and Compilers
4204/18/23
List.find and anonymous functions
List.find (fn x => x = "Tim")
["Tom", "Jane"];
val it = NONE : string option
List.find (fn x => even x andalso x>10)
[2,4,5,12];
val it = SOME 12 : int option
Cse321, Programming Languages and Compilers
4304/18/23
List.filter
Filter keeps some elements, and throws away others.– List.filter : ('a -> bool) -> 'a list -> 'a list
It uses a function (p) as a parameter to decide which elements to keep (p x = true), and which to throw away (p x = false)
val ex6 = List.filter even [1,2,3,4,5,6];
val ex6 = [2,4,6] : int list
Cse321, Programming Languages and Compilers
4404/18/23
List.filter and anonymous functionsval people = [("tim",22),("john",18),("jane",25),("tim",8)];
val ex7 = filter
(fn (nm,age) => nm <> "tim" orelse age>10)
people;
val ex7 =
[("tim",22),("john",18),("jane",25)]
: (string * int) list
Cse321, Programming Languages and Compilers
4504/18/23
List.exists
• “exists” is like “find” in that it searches a list– but rather than the element that completes the search it is only
interested in if such an element exists.– List.exists : ('a -> bool) -> 'a list -> bool
• Uses a function as a parameter to determine if the search is successful.
val ex8 = List.exists even [2,3,5];
val ex8 = true : bool
• Note that even if only 1 element in the list causes the function to be true, exists returns true.
Cse321, Programming Languages and Compilers
4604/18/23
List.all
• List.all tests elements in a list for a property. It returns true only if every element has that property.– List.all : ('a -> bool) -> 'a list -> bool
• Uses a function as a parameter to perform the test.
val ex9 = List.all even [2,4,5];
val ex9 = false : bool
• List.exists and List.all are related functions. They are duals.– not(List.all p xs) = List.exists (fn x => not(p x)) xs
Cse321, Programming Languages and Compilers
4704/18/23
List.foldr captures a pattern
• Add up every element in a list.
fun sum [] = 0
| sum (x::xs) = x + (sum xs);
• Compute the maximum element in a list of natural numbers (Integers >= 0).
fun maximum [] = 0
| maximum (x::xs) = Int.max(x,maximum xs);
• Compute if every element in a list of boolean is true.
fun allTrue [] = true
| allTrue (x::xs) = x andalso (allTrue xs);
Cse321, Programming Languages and Compilers
4804/18/23
Patternfun sum [] = 0
| sum (x::xs) = x + (sum xs);
fun maximum [] = 0
| maximum (x::xs) = Int.max(x,maximum xs);
fun allTrue [] = true
| allTrue (x::xs) = x andalso (allTrue xs);
fun foldr acc base [ ] = base
| foldr acc base (x::xs)
= acc(x,foldr acc base xs);
Cse321, Programming Languages and Compilers
4904/18/23
See the pattern in use.fun sum [] = 0
| sum (x::xs) = x + (sum xs);
fun sum xs = foldr (op +) 0 xs;
fun maximum [] = 0
| maximum (x::xs) = Int.max(x,maximum xs);
fun maximum xs = foldr Int.max 0 xs;
fun allTrue [] = true
| allTrue (x::xs) = x andalso (allTrue xs);
fun allTrue xs =
foldr (fn (a,b) => a andalso b) true xs;
Cse321, Programming Languages and Compilers
5004/18/23
Take another lookWhat does this function do?
fun ok [] = false
| ok xs = not(exists (fn ys => xs=ys) (!old))
andalso
not(exists (fn ys => xs=ys) (!worklist))
Cse321, Programming Languages and Compilers
5104/18/23
The Option Library- open Option;opening Option datatype 'a option = NONE | SOME of 'a exception Option val getOpt : 'a option * 'a -> 'a val isSome : 'a option -> bool val valOf : 'a option -> 'a val filter : ('a -> bool) -> 'a -> 'a option val join : 'a option option -> 'a option val app : ('a -> unit) -> 'a option -> unit val map : ('a -> 'b) -> 'a option -> 'b option val mapPartial : ('a -> 'b option) -> 'a option -> ‘ b option
Cse321, Programming Languages and Compilers
5204/18/23
Interesting functions that use Options• Int.fromString: string -> int option
Int.fromString "234";
val it = SOME 234 : int option
Int.fromString "abc";
val it = NONE : int option
• String.extract: string * int * int option -> stringString.extract("abcde",1,SOME 3);
val it = "bcd" : string
String.extract("abcde",1,NONE);
val it = "bcde" : string
Cse321, Programming Languages and Compilers
5304/18/23
More option functions• List.find: ('a -> bool) -> 'a list -> 'a option
List.find even [1,3,5];
val it = NONE : int option
List.find (fn x => x="tim") ["tom","tim","jane"];
val it = SOME "tim" : string option
• List.getItem: 'a list -> ('a * 'a list) option– List.getItem [1,2,3,4];– val it = SOME (1,[2,3,4])
– List.getItem [];– val it = NONE
Cse321, Programming Languages and Compilers
5404/18/23
Using While Loopsfun ident c cs = let val xs = ref cs val x = ref c val ans = ref [] in while (not(null(!xs)) andalso Char.isAlpha (hd (!xs))) do ( ans := !ans @ [!x] ; x := hd(!xs) ; xs := tl(!xs) ); (Id (String.implode (!ans @ [!x])), !xs)
end
Don’t forget to test for empty list