A Crash Course on Standard ML

Similar documents
About coding style Spring February 9, 2004

Supplementary Notes on Concurrent ML

The ATS Programming Language

Handout 2 August 25, 2008

CSci 4223 Principles of Programming Languages

SML A F unctional Functional Language Language Lecture 19

Version 4, 12 October 2004 Project handed out on 12 October. Complete Java implementation due on 2 November.

Datatype declarations

Exercises on ML. Programming Languages. Chanseok Oh

CSE 341 Section 5. Winter 2018

Metaprogramming assignment 3

7.3.3 A Language With Nested Procedure Declarations

Computer Science 312 Fall Prelim 2 SOLUTIONS April 18, 2006

COP-5555 PROGRAMMING LANGUAGEPRINCIPLES NOTES ON RPAL

Specification and Verification in Higher Order Logic

Functional programming Primer I

Lists. Michael P. Fourman. February 2, 2010

Programming in Standard ML: Continued

CSE-321 Programming Languages 2010 Midterm

1 Announcements. 2 Scan Implementation Recap. Recitation 4 Scan, Reduction, MapCollectReduce

CS 312 Problem Set 1: An Introduction to SML

Chapter 3 Linear Structures: Lists

CSE341 Autumn 2017, Midterm Examination October 30, 2017

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

THAT ABOUT WRAPS IT UP Using FIX to Handle Errors Without Exceptions, and Other Programming Tricks

Chapter 3 Linear Structures: Lists

Programming Languages

Factorial. Next. Factorial. How does it execute? Tail recursion. How does it execute? More on recursion. Higher-order functions

A First Look at ML. Chapter Five Modern Programming Languages, 2nd ed. 1

BNDN F2013: Software Development in Large Teams with International Collaboration C# Quiz

CS Lectures 2-3. Introduction to OCaml. Polyvios Pratikakis

Next. Tail Recursion: Factorial. How does it execute? Tail recursion. Tail recursive factorial. Tail recursive factorial.

CSE-321 Programming Languages 2012 Midterm

Lecture 2: The Basis of SML

Pattern Matching and Abstract Data Types

CSCI-GA Scripting Languages

Homework 3 COSE212, Fall 2018

SMURF Language Reference Manual Serial MUsic Represented as Functions

A quick introduction to SML

OCaml. ML Flow. Complex types: Lists. Complex types: Lists. The PL for the discerning hacker. All elements must have same type.

Some Advanced ML Features

Inductive Data Types

All the operations used in the expression are over integers. a takes a pair as argument. (a pair is also a tuple, or more specifically, a 2-tuple)

Computer Science CSC324 Wednesday February 13, Homework Assignment #3 Due: Thursday February 28, 2013, by 10 p.m.

15 150: Principles of Functional Programming. Exceptions

COP4020 Programming Language Concepts Spring 2017 Sample Final Exam Questions SOLUTIONS

Introduction to Programming in ATS

A Third Look At ML. Chapter Nine Modern Programming Languages, 2nd ed. 1

CS109A ML Notes for the Week of 1/16/96. Using ML. ML can be used as an interactive language. We. shall use a version running under UNIX, called

Recap: Functions as first-class values

Introduction to OCaml

9/23/2014. Function: it s easy and it is fun Local Function & Composite Function Polymorphic function I/O Structure and signature

Verification of an ML compiler. Lecture 3: Closures, closure conversion and call optimisations

General Computer Science (CH ) Fall 2016 SML Tutorial: Practice Problems

Two approaches to writing interfaces

Typed Racket: Racket with Static Types

Online Resource. Online introductory book on programming in SML (Standard ML): online.pdf

Language Sequence. The Algol Family and ML. Algol 60 Sample. Algol 60. Some trouble spots in Algol 60. Algol Joke. John Mitchell

Functional Programming

CSC/MAT-220: Lab 6. Due: 11/26/2018

CSE 341: Programming Languages

Introduction to SML Basic Types, Tuples, Lists, Trees and Higher-Order Functions

The Typed Racket Guide

CSC324- TUTORIAL 5. Shems Saleh* *Some slides inspired by/based on Afsaneh Fazly s slides

Typed Scheme: Scheme with Static Types

Subtyping: An introduction

A Second Look At ML. Chapter Seven Modern Programming Languages, 2nd ed. 1

CMSC330. Objects, Functional Programming, and lambda calculus

Why Standard ML? A language particularly suited to compiler implementation.

Products and Records

Introduction to SML Getting Started

Preparing for Class: Watch le Videos! What is an ML program?

# true;; - : bool = true. # false;; - : bool = false 9/10/ // = {s (5, "hi", 3.2), c 4, a 1, b 5} 9/10/2017 4

Overview. A normal-order language. Strictness. Recursion. Infinite data structures. Direct denotational semantics. Transition semantics

Today. Recap from last Week. Factorial. Factorial. How does it execute? How does it execute? More on recursion. Higher-order functions

CS 457/557: Functional Languages

Control in Sequential Languages

Mini-ML. CS 502 Lecture 2 8/28/08

Specification, Implementation, and Use

Introduction to Objective Caml

Why OCaml? Introduction to Objective Caml. Features of OCaml. Applications written in OCaml. Stefan Wehr

15 212: Principles of Programming. Some Notes on Continuations

CSCC24 Functional Programming Typing, Scope, Exceptions ML

Introduction to ML. Based on materials by Vitaly Shmatikov. General-purpose, non-c-like, non-oo language. Related languages: Haskell, Ocaml, F#,

Second Exam CS 1101 Computer Science I Spring Section 03 KEY. Thursday April 14, Instructor Muller Boston College

Type Checking and Type Inference

Introduction to OCaml

Chapter 2 SML, a Functional Programming Language

2.1. Expressions. Chapter 2 SML, a Functional Programming Language. Integers. Interacting with ML

CSE3322 Programming Languages and Implementation

Plan (next 4 weeks) 1. Fast forward. 2. Rewind. 3. Slow motion. Rapid introduction to what s in OCaml. Go over the pieces individually

CS 312. Lecture April Lazy Evaluation, Thunks, and Streams. Evaluation

Begin at the beginning

CSE 307: Principles of Programming Languages

Announcements. CSCI 334: Principles of Programming Languages. Lecture 5: Fundamentals III & ML

CSE 307: Principles of Programming Languages

G Programming Languages - Fall 2012

The Algol family and ML

A Short Introduction to OCaml

CMSC 330: Organization of Programming Languages. Rust Basics

Transcription:

A Crash Course on Standard ML Hongwei Xi Version of November 23, 2004 1 Start Type sml-cm at a Unix wdow to get an teractive terpreter for Standard ML (SML). You can later quit the terpreter by typg ctrl-d. 2 Generalities At the prompt, which is a dash symbol -, you can type an expression or a declaration. Here are some examples on evaluatg expressions. - 1+2; val it = 3 : t - "Hello" ^ " world!"; val it = "Hello world!" : strg - prt "Hello, world!\n"; Hello, world! val it = () : unit - fn x:t => x + 1; val it = fn : t -> t Each time you type a semicolon followed by Enter, you get your expression evaluated. If you just press Enter without a semicolon preceedg it, the terpreter gives a contuation prompt =, allowg you to type a new le without evaluatg what you have just written. You can also troduce declarations as follows, which bd n and f to 0 and the successor function on tegers, respectively. - val n = 0; val n = 0 : t - val f = fn x => x+1; val f = fn : t -> t The arithmetic operators (the unary mus operator), +, and are overloaded; they can take either teger or real arguments. For stance, we have - 1 + 1; val it = 2 : t - 1.0 + 1.0; val it = 2.0 : real - ~(2-1); val it = ~1 : t 1

The division operators div and / take tegers and reals, respectively. For stance, we have - 6 div 3; val it = 2 : t - 6.0 / 3.0; val it = 2.0 : real Note that the expression 6 / 3 is ill-typed. 3 Expressions We have seen examples of arithmetic expressions and strg expressions. We now troduce more forms of expressions. 3.1 -expressions We can also form an expression volvg some local declarations as follows. val x = 1 fun f (x:t) = x + x f(x) * f(x) 3.2 if-then-else-expressions The syntax for if-then-else expressions SML is as follows, if <exp_0> then <exp_1> else <exp_2> where the expression exp 0 needs to have the type bool and the expressions exp 1 and exp 2 must have the same type. 3.3 case-expressions Another form of expression volves pattern matchg, case <exp_0> of <pat_1> => <exp_1>...... <pat_n> => <exp_n> which evaluates exp 1 to a value v, chooses the first clause pat i exp i such that v matches pat i, and then evaluates exp i after troducg some proper bdgs for the variable pat i. If v matches none of the patterns pat 1,..., exp n, a Match exception is raised. In particular, the above if-then-else expression is equivalent to the followg expression. case <exp_0> of true => <exp_1> false => <exp_2> We are to say more about patter matchg later. 2

3.4 Tuples and Records You can readily form tuples and select from tuples. Here is an example. - val x = (1, true, #"a", "a"); val x = (1,true,#"a","a") : t * bool * char * strg - #1 (x); val it = 1 : t - #2 (x); val it = true : bool - #3 (x); val it = #"a" : char - #4 (x); val it = "a" : strg For a tuple of length n, there are n projections #1,..., #n for selectg the components of the tuple. A record is basically a tuple with field name. The orderg of the components a record is irrelevant. For stance, {x = 0, y = false} is equivalent to {y = false, x = 0}. Here is an example of formg and selectg from a record. - val r = {a = 1, b = true, c = #"a", d = "a"}; val r = {a=1,b=true,c=#"a",d="a"} : {a:t, b:bool, c:char, d:strg} - #a(r); val it = 1 : t - #b(r); val it = true : bool - #c(r); val it = #"a" : char - #d(r); val it = "a" : strg For a record with a field name n, #n is the selector for selectg the value associated with the field name n the record. Note that a tuple is just syntactic sugar for a records with teger fields. For stance, (0, false) is really for the record {1 = 0, 2 = false}. 4 Functions We can declare a recursive function SML as follows. val rec f91: t -> t = fn n => if n <= 100 then f91 (f91 (n+11)) else n - 10 It is required that the right-hand side of a declaration followg the keyword val rec be a function expression. The function f91 can also be declared through the followg syntax, fun f91 (n:t): t = if n <= 100 then f91 (f91 (n+11)) else n-10 which should really be regarded as syntactic sugar for the function declaration given previously. The followg example declares two mutually recursive functions. 3

fun even (n:t): bool = if n = 0 then true else odd (n-1) and odd (n: t): bool = if n = 0 then false else even (n-1) When defg a function, we may often defe some help functions or auxiliary functions. The followg declaration is such an example. fun fib (n: t): t = fun aux (n: t): t * t = if n = 0 then (1, 0) else val (x, y) = aux (n-1) (x+y, x) #2 (aux (n)) Note that if you want a function to return multiple values then you can make the function to return a tuple contag these values. The ner function aux the above example is such a case. 5 Datatypes You can declare datatypes to model various data structures. For stance, the followg declaration forms a datatype for bary trees with teger labelled branchg nodes. datatype bary_tree = E B of bary_tree * t * bary_tree The function computg the height of a bary tree can be defed as follows through the use of pattern matchg. fun height E = 0 heigth (B (lt, _, rt)) = 1 + max (height lt, height rt) For stance, height(b(e, 0, B(E, 1, E))) evaluates to 2. The followg is a more terestg example, where a datatype is declared for representg untyped λ-terms usg debruijn dices. datatype lambda_expr1 = One Shift of lambda_expr1 Lam of lambda_expr1 App of lambda_expr1 * lambda_expr1 For stance, the λ-term λx.λy.x(y) can be represented as follows. Lam(Lam(App(Shif t(one), One))) We can also use higher-order abstract syntax to represent closed λ-terms. 4

datatype lambda_expr2 = Lam of (lambda_expr2 -> lambda_expr2) App of lambda_expr2 * lambda_expr2 For stance, the λ-term λx.λy.x(y) can be represented as follows. Lam(fn x (Lam(fn y App(x, y)))) A name startg with a sgle quote stands for a type variable. The followg declaration troduces a datatype constructor rbtree that forms the type (τ)rbtree when applied a type τ. datatype a rbtree = E R of a rbtree * a * a rbtree B of a rbtree * a * a rbtree For stance, you can now have: - val x = B(E, 0, E); val x = B (E,0,E) : t rbtree - val y = B(E, true, E); val y = B (E,true,E) : bool rbtree 6 Lists In SML, list is a built- type constructor. Given a type τ, (τ)list is the type for lists which each element is of type τ. The constructor nil represents the empty list, and the fix constructor :: (with right associativity) takes an element and a list to form another list. For stance, 1 :: 2 :: 3 :: nil is a list of type t list. Alternatively, you may write [] for nil and [1, 2, 3] for 1 :: 2 :: 3 :: nil. There are already various built- functions on lists. As an example, the followg program implements a function that reverses a given list. fun reverse (xs: a list): a list = fun aux ys = fn [] => ys x :: xs => aux (x :: ys) xs aux [] xs 7 Arrays There is a built- type constructor array SML, take a type τ to form the type (τ)array for arrays which each element is of type τ. The functions array, sub and update are given the followg types and their meang should be obvious. val array: t * a -> a array val length: a array -> t val sub: a array * t -> a val update: a array * t * a -> unit The followg example implements the dot product function on two real vectors. 5

fun dotprod (v1: real array, v2: real array): real = val n1 = length v1 val n2 = length v2 fun aux (i:t, s: real): real = if i < n1 then aux (i+1, s + sub (v1, i) * sub (v2, i)) else s if n1 = n2 then aux (0, 0.0) else raise Unequal_array_length Please see the next section for the use of exception this example. 8 Exceptions The exception mechanism SML offers an approach to alter the normal control flow program execution. Declarg an exception is similar to delarg a datatype. exception Fatal fun fatal (msg: strg) = (prt msg; raise Fatal) In the above code, a call to fatal with an argument msg prts out msg before raisg the exception F atal. The followg program implements a function that tests whether a given bary tree is perfectly balanced. Notice the terestg use of exception this program. fun is_perfect (t: bary_tree): bool = exception Not_perfect fun aux (E) = 0 aux (B (lt, _, rt)) = val lh = aux lt val rh = aux rt if lh = rh then 1 + lh else raise Not_perfect val _ = aux (t) true handle Not_perfect => false 9 References References are similar to poters C. For stance, the followg declaration val x = ref 0 6

allocates some memory to store the teger value 0 and then bds the memory location to x. Note that the expression ref 0 itself is not a value; the reference returned from evaluatg the expression is a value, but such a value cannot be expressed explicity SML. After the declaration, the type of x is t ref. You cannot change the bdg of x but you can update the value stored the memory location to which x is bound. For stance, the value is updated to 1 after the expression x := 1 is evaluated. In general, an expression of the form e 1 := e 2 evaluates e 1 to a reference r and e 2 to a value v, and then store the value v the memory location bound to the reference r. The dereference operator is!. For stance,!e evaluates e to a reference r and then returns the value store the memory location bound to r. Equality on references is the usual poter equality. Also, you may use ref to form patterns. What does the followg function c do? fun c ((r as ref n): t ref): unit = (r := n+1) The followg program SML is an implementation of the factorial function volvg the use of references. fun factorial (n:t): t = val result: t ref = ref 1 fun loop (i: t): t = if i > n then!result else (result := i *!result; loop (i+1)) loop (1) 10 Higher-Order Functions In general, the type of a function f is of the form τ 1 τ n τ, where n 1 and τ 1,..., τ n, τ are types. If τ i contas an occurrence of for some i i n, the f is a higher-order function. For stance, the followg function zero fder is a higher-order function sce its type is (t t) t. fun zero_fder (f: t -> t): t = fun aux (i: t): t = if f(i) = 0 then i else if i > 0 then aux (~i) else aux (~i+1) aux (0) Given a function f of the type t t, zero fder(f ) fds through brute-force search the first n the list 0, 1, 1, 2, 2,... of tegers such that f(n) = 0; it loops forever if f has no zeros. A commonly used function map can be defed as follows, which applies a given function f to each element of a given list and then collects the return results a list. 7

fun map f ([]) = [] map f (x :: xs) = f (x) :: map f xs The type of map is ( a -> b) -> a list -> b list written the syntax of SML. The followg function is similar to map, which applies a given function f with unit as its return type to each member a given list. fun foreach (f: a -> unit) = fn [] => () x :: xs => (f (x); foreach f xs) The type of foreach is ( a -> unit) -> a list -> unit written the syntax of SML. 11 Contuations In SML/NJ, there are two functions callcc and throw the module SMLofNJ.Cont for supportg programmg with contuations. val callcc : ( a cont -> a) -> a val throw : a cont -> a -> b val isolate: ( a -> unit) -> a cont As an example, we implement a function comp fun cont that composes a function with a contuation. fun comp_fun_cont (f: a -> b) (E: b cont): a cont = callcc (fn E0 => throw E (f (callcc (fn E1 => throw E0 E1)))) fun comp_fun_cont (f: a -> b) (E: b cont): a cont = isolate (fn x: a => throw E (f x)) For stance, the factorial function can be implemented as follows the contuation-passg style. fun factorial (n: t): t = fun aux (n: t) (E: t cont): t = if n = 0 then throw E 1 else aux (n-1) (comp_fun_cont (fn (res:t) => n * res) E) callcc (fn E => aux n E) Also, the previously defed function is perfect can now be implemented as follows. fun is_perfect (t: bary_tree): bool = fun aux (k: bool cont) (t: bary_tree): t = case t of E => 0 B (lt, _, rt) => val lh = aux k lt val rh = aux k rt 8

if lh = rh then 1 + lh else throw k false callcc (fn k => val _ = aux k t true ) 12 Module System There are three major gredients the module system of Standard ML. Structures: a structure SML is basically a collection of declarations for types, values, exceptions and structures. Signatures: a signature is basically a structure terface; some sense, it is the type of a structure. Functors: a functor is basically a structure parameterized over structures; some sense, it is a function from structures to structures. 12.1 Structures structure S = struct val x = 0 fun f (x:t): bool = (x <> 0) type t = bool * t list datatype bary_tree = E B of bary_tree * t * bary_tree exception Fatal structure T =...... You may refer to a component S by appg S. to the front of the name of the component. For stance, S.x evaluates to 3; S.f(S.x) evaluates to 4; S.t is equivalent to bool tlist; S.E and S.B have the types S.bary tree and S.bary tree t S.bary tree S.bary tree, respectively; S.F atal is an exception; S.T is a structure;... 12.2 Signatures Signatures provide an approach to specifyg an terface to a structure. For stance, the followg signature is one that the above structure S can match. However, a structure may have additional components that are not specified a signature that the structure matches. signature SIG_FOR_S = sig val x: t fun f: t -> bool type t datatype bary_tree = E B of bary_tree * t * bary_tree exception Fatal structure T: SIG_FOR_T 9

signature RATIONAL = sig type rat val make: t * t -> rat val tostrg: rat -> strg val zero: rat val one: rat val op~: rat -> rat val op+: rat * rat -> rat val op-: rat * rat -> rat val op*: rat * rat -> rat val op/: rat * rat -> rat val iszero: rat -> bool val ispositive: rat -> bool val isnegative: rat -> bool val op>: rat * rat -> bool val op>=: rat * rat -> bool val op<: rat * rat -> bool val op<=: rat * rat -> bool structure Rational :> RATIONAL = struct type t = t * t exception DenomatorIsZero fun gcd (p: t, q: t) = if p = 0 then q else gcd (q mod p, p) fun make0 (p: t, q: t) = (* q is assumed to be positive *) val r = if p > 0 then gcd (p, q) else gcd (~p, q) (p div r, q div r) fun make (p: t, q: t): rat = if q = 0 then raise DenomnatorIsZeor else if q > 0 then make0 (p, q) else make0 (~p, ~q)...... 10

12.3 Functors 13 Compilation Manager 14 Libraries 11