Slides to accompany Ullman’s Functional Programming with ML CS 631 Principles of Programming Languages.

Slides:



Advertisements
Similar presentations
More ML Compiling Techniques David Walker. Today More data structures lists More functions More modules.
Advertisements

Modern Programming Languages, 2nd ed.
A First Look at ML.
A Third Look At ML 1. Outline More pattern matching Function values and anonymous functions Higher-order functions and currying Predefined higher-order.
Type Checking, Inference, & Elaboration CS153: Compilers Greg Morrisett.
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists Dan Grossman Winter 2013.
CMSC 330: Organization of Programming Languages Tuples, Types, Conditionals and Recursion or “How many different OCaml topics can we cover in a single.
ML Lists.1 Standard ML Lists. ML Lists.2 Lists  A list is a finite sequence of elements. [3,5,9] ["a", "list" ] []  ML lists are immutable.  Elements.
ML Datatypes.1 Standard ML Data types. ML Datatypes.2 Concrete Datatypes  The datatype declaration creates new types  These are concrete data types,
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Chapter ElevenModern Programming Languages1 A Fourth Look At ML.
A Fourth Look At ML Chapter ElevenModern Programming Languages, 2nd ed.1.
A First Look at ML Chapter FiveModern Programming Languages, 2nd ed.1.
Patterns in ML functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are the.
CS 355 – PROGRAMMING LANGUAGES Dr. X. Apply-to-all A functional form that takes a single function as a parameter and yields a list of values obtained.
Introduction to ML – Part 1 Frances Spalding. Assignment 1 chive/fall05/cos441/assignments/a1.ht m
5/11/2015IT 3271 Types in ML (Ch 11) datatype bool = true | false; datatype 'element list = nil | :: of 'element * 'element list n Predefined, but not.
Compiler Construction
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Introduction to ML - Part 2 Kenny Zhu. What is next? ML has a rich set of structured values Tuples: (17, true, “stuff”) Records: {name = “george”, age.
Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.
CSE 341 Lecture 6 exceptions; higher order functions; map, filter, reduce Ullman 5.2, 5.4 slides created by Marty Stepp
Last Time Introduction Course Logistics Introduction to ML Base Types Tuples and Records Functions & Polymorphism See Harper ’ s Intro to ML.
Chapter 9: Arrays and Strings
Crash course on SML Wojciech Moczydłowski SML – functional programming language Complete formal semantics Extremely convenient for writing compilers, interpreters,
1 Functional Programming and ML. 2 What’s wrong with Imperative Languages? State State Introduces context sensitivity Introduces context sensitivity Harder.
Chapter 2 Data Types, Declarations, and Displays
Chapter 8 Arrays and Strings
ML Introduction.1 Standard ML Introduction. ML Introduction.2 Includes: Most of the examples Most of the questions Most of the answers... Recommended.
CS 2104 : Prog. Lang. Concepts. Functional Programming I Lecturer : Dr. Abhik Roychoudhury School of Computing From Dr. Khoo Siau Cheng’s lecture notes.
Objectives You should be able to describe: Data Types
Lists in Python.
ML Datatypes.1 Standard ML Data types. ML Datatypes.2 Concrete Datatypes  The datatype declaration creates new types  These are concrete data types,
Chapter 8 Arrays and Strings
CSE-321 Programming Languages Introduction to Functional Programming (Part II) POSTECH March 13, 2006 박성우.
Patterns in OCaml functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are.
Introduction to Functional Programming and ML CS 331 Principles of Programming Languages.
CSC 580 – Theory of Programming Languages, Spring, 2009 Week 9: Functional Languages ML and Haskell, Dr. Dale E. Parson.
Flow of Control Part 1: Selection
C++ Programming: From Problem Analysis to Program Design, Fifth Edition Arrays.
Introduction to ML CS 331 Principles of Programming Languages revised Spring 2003.
Chapter 9: Functional Programming in a Typed Language.
Functional Programming With examples in F#. Pure Functional Programming Functional programming involves evaluating expressions rather than executing commands.
A Second Look At ML 1. Outline Patterns Local variable definitions A sorting example 2.
Overview of the Haskell 98 Programming Language
A Third Look At ML Chapter NineModern Programming Languages, 2nd ed.1.
0 Odds and Ends in Haskell: Folding, I/O, and Functors Adapted from material by Miran Lipovaca.
Python Primer 1: Types and Operators © 2013 Goodrich, Tamassia, Goldwasser1Python Primer.
1 CS 457/557: Functional Languages Lists and Algebraic Datatypes Mark P Jones Portland State University.
Error Example - 65/4; ! Toplevel input: ! 65/4; ! ^^ ! Type clash: expression of type ! int ! cannot have type ! real.
Introduction to Objective Caml. General comments ML is a purely functional language--there are (almost) no side effects There are two basic dialects of.
Chapter SevenModern Programming Languages1 A Second Look At ML.
A FIRST LOOK AT ML Chapter Five Modern Programming Languages 1.
1 FP Foundations, Scheme In Text: Chapter Chapter 14: FP Foundations, Scheme Mathematical Functions Def: A mathematical function is a mapping of.
Arrays Declaring arrays Passing arrays to functions Searching arrays with linear search Sorting arrays with insertion sort Multidimensional arrays Programming.
Cs776(Prasad)L6sml971 SML-97 Specifics SML/NJ 110.
1.SML Docs Standard Basis 2.First-Class Functions Anonymous Style Points Higher-Order 3.Examples Agenda.
1 Objective Caml (Ocaml) Aaron Bloomfield CS 415 Fall 2005.
Principles of programming languages 12: Functional programming
Types CSCE 314 Spring 2016.
ML: a quasi-functional language with strong typing
Objective caml Daniel Jackson MIT Lab for Computer Science 6898: Advanced Topics in Software Design March 18, 2002.
FP Foundations, Scheme In Text: Chapter 14.
Agenda SML Docs First-Class Functions Examples Standard Basis
Agenda SML Docs First-Class Functions Examples Standard Basis
CSE 341 Section 5 Winter 2018.
Python Primer 1: Types and Operators
CSE-321 Programming Languages Introduction to Functional Programming
COMPUTER PROGRAMMING SKILLS
Presentation transcript:

Slides to accompany Ullman’s Functional Programming with ML CS 631 Principles of Programming Languages

Features of ML A pure functional language – serious programs can be written without using variables Widely accepted –reasonable performance (claimed) –can be compiled –syntax not as arcane (or as simple) as LISP

In these slides, We use Standard ML of New Jersey Runs on PCs, Linux, and other flavors of UNIX Much of this material is based on Ullman’s book, Elements of ML Programming See the SML documentation at

Running SML on UNIX On the cs machines, make sure the directory /cs/sml/bin is in your path. Then invoke sml from a shell prompt with the command sml Use control d to exit interpreter

Chapter 2 Getting Started in ML

Hello, world in SML Standard ML of New Jersey, - print("Hello world\n"); Hello world val it = () : unit -

Arithmetic in ML Copy and paste the following text into a Standard ML window 2+2; (* note semicolon at end*) 3*4; 4/3; (* an error! *) 6 div 2; (* integer division *) 7 div 3;

It should look like this

Declaring Constants Constants are not exactly the same as variables –they can be redefined, but existing uses of that constant (e.g. in function definitions) aren’t affected by such redefinition val freezingFahr = 32;

Ints and Reals Int.abs ~3; Int.sign ~3; Int.max (4, 7); Int.min (~2, 2); real(freezingFahr); Math.sqrt real(2); Math.sqrt(real(2)); Math.sqrt(real 3); Note ~ is unary minus min and max take just two input arguments, but that can be fixed! The real operator converts to real Parens can sometimes be omitted, but I don’t recommend it

- Int.abs ~3; val it = 3 : int - Int.sign ~3; val it = ~1 : int - Int.max (4, 7); val it = 7 : int - Int.min (~2, 2); val it = ~2 : int - Math.sqrt real(2); stdIn: Error: operator and operand don't agree [tycon mismatch] operator domain: real operand: int -> real in expression: Math.sqrt real - Math.sqrt(real(2)); val it = : real - Math.sqrt(real 3); val it = : real

Strings Delimited by double quotes the caret mark ^ is used for string concatenation, e.g. “house”^”cat” \n is used for newline, as in C and C++

Comparison Operators The usual, = and <> are available For reals, = and <> are not available –For reals a and b, a = b is an equality test The connectors “andalso” and “orelse” are logical operators with short-circuit evaluation

If Then Else If Then Else is an expression, not a control structure Example, if quotient, dividend and divisor are reals, we might have val quotient = if divisor > 0 then dividend/divisor else 0

Tuples Tuples are data items drawn from a Cartesian product type. Example: type fraction = int * int; val foo: fraction = (44,100); #1(foo); (* returns 44 *) #2(foo); (* returns 100 *) Tuples are of fixed size, e.g. 2 in this example

Lists in ML Objects in a list must be of the same type –[1,2,3]; –[“dog”, “cat”, “moose”]; The empty list is written [] or nil

Making Lists operator is used to concatenate two lists of the same type The :: operator makes a new list in which its first operand is the new first element of a list which is otherwise like the second operand. The functions hd and tl give the first element of the list, and the rest of the list, respectively

List Operations - val list1 = [1,2,3]; val list1 = [1,2,3] : int list - val list2 = [3,4,5]; val list2 = [3,4,5] : int list - val it = [1,2,3,3,4,5] : int list - hd list1; val it = 1 : int - tl list2; val it = [4,5] : int list

More List Operations - val list1 = [1,2,3]; val list1 = [1,2,3] : int list - val list2 = [3,4,5]; val list2 = [3,4,5] : int list - 4::list1; val it = [4,1,2,3] : int list - val list3 = list1::list2; val list3 = [[1,2,3],3,4,5] - length(list3); val length(list3) = 4

Strings and Lists The explode function converts a string into a list of characters The implode function converts a list of characters into a string Examples: - explode("foo"); val it = [#"f",#"o",#"o"] : char list - implode [#"c",#"a",#"t"]; val it = "cat" : string -

Heads and Tails The cons operator :: takes an element and prepends it to a list of that same type. For example, the expression 1::[2,3] results in the list [1,2,3] What’s the value of [1,2]::[ [3,4], [5,6]] ? What’s the value of x::[], for any atom x?

Chapter 3 Defining Functions

Declaring Functions A function takes an input value and returns an output value ML will figure out the types fun fahrToCelsius f = (f -freezingFahr) * 5 div 9; fun celsiusToFahr c = c * 9 div 5 + freezingFahr;

Notes ML is picky about not mixing types, such as int and real, in expressions The value of “it” is always the last value computed Function arguments don’t always need parentheses, but it doesn’t hurt to use them

Types of arguments and results ML figures out the input and/or output types for simple expressions, constant declarations, and function declarations If the default isn’t what you want, you can specify the input and output types, e.g. fun divBy2 x:int = x div 2 : int; fun divideBy2 (y : real) = y / 2.0; divBy2 (5); divideBy2 (5.0);

Two similar divide functions - fun divBy2 x:int = x div 2 : int; val divBy2 = fn : int -> int - fun divideBy2 (y : real) = y / 2.0; val divideBy2 = fn : real -> real - divBy2 (5); val it = 2 : int - divideBy2 (5.0); val it = 2.5 : real -

Functions and Patterns Recall that min and max take just two arguments However, using the fact that, for example, –min(a, b, c) = min(a, min(b, c))

Generalizing Min An example of ML pattern matching –the cons notation x::xs is both a binary constructor and a pattern –cases aren’t supposed to overlap Note that lists of any size are supported –but the elements are expected to be integers –checking that the rest of the list is non-empty is critical - but why?

(* Sample ML program - MinList *) (* Takes a list of integers as input, and returns a list with at most one element, i.e. the smallest element in the list *) fun MinList([]) = [] | MinList(x::xs) = if null(xs) then [x] else [Int.min(x,hd(MinList(xs)))]; MinList([]); MinList([1,2]); MinList([315, 41, 59, 265, 35, 897]);

When we run MinList,… - use "../MinList.sml"; [opening../MinList.sml] val MinList = fn : int list -> int list val it = [] : int list val it = [1] : int list val it = [35] : int list val it = () : unit

Building trees It’s easy to build recursive data types in ML Some examples follow

(* Sample ML program - Abstract Syntax Trees *) (* Declare the ast datatype *) datatype ast = empty | leaf of int | node of string*ast*ast; fun traverse(empty) = print "empty tree" | traverse(leaf(n)) = (print (Int.toString(n)); print " ") | traverse(node(operator, left, right)) = ( traverse(left); print operator; traverse(right)); fun prefix(tree:ast) = (traverse(tree); print "\n"); prefix(empty); prefix(leaf(4)); prefix(node("*",node("+",leaf(5),leaf(3)),node("-",leaf(10),leaf(4))));

Two ways to count (* count from i to j *) fun countUp(i:int, j:int) = if i=j then print(" "^Int.toString(j)) else (countUp(i,j-1);print(" "^Int.toString(j))); (* count from i to j *) fun TcountUp(i:int, j:int) = if i=j then print(" "^Int.toString(j)^"\n") else (print(" "^Int.toString(i));TcountUp(i+1,j));

What about control structures? Well, there aren’t any in the usual (procedural) sense If then else, case, and iteration are all accomplished by evaluation of expressions

Iteration vs. Recursion (* note that F is a functional parameter *) fun loopIt(i:int,n:int,F) = if i = n then F(i) else let val dummy = F(i) val dummy2 = loopIt(i+1,n,F) in dummy2 (* any expression could be used *) end;

Chapter 4 Input and Output

The Print Function print(“This string\n”); print(“2+2 is “^Int.toString(2+2)^”\n”); Expressions may be grouped with parentheses, e.g (print(“a”);print(“b”)) But the grouped expressions may not change the environment, so this is not the same as a block in a procedural language

More About I/O To access functions in the TextIO structure, open TextIO; To open a file openIn(“somefile”); The value returned is of type instream endOfStream(file:instream): bool inputN(file:instream,n:int):string input(file:stream):string (* whole file *)

The option type constructor The function input1(file) returns a value of type char option, which means that input1 returns –SOME c, where c is a character, or –NONE The option type constructor can be used with lots of types, not just char

Char option example fun makeList1(infile, NONE) = nil | makeList1(infile, SOME c) = c::makeList1(infile, input1(infile)); or fun makeList1(infile, c) = if isSome(c) then valOf(c)::makeList1(infile, input1(infile)) else nil; In these examples, input1 is used to build a list of the characters in a file

Chapter 5 More About Functions

Matches and Functions Example of match expression: val rec reverse = fn nil => nil| x::xs => [x]; The rec keyword stands for “recursive”, which is necessary because the binding of reverse as a function name is not yet established

Anonymous Functions Functions don’t have to have names, e.g. (fn x => x+1) (3) yields 4 Such functions can be passed as parameters, e.g. for use in the map or reduce functions, to be discussed later in this chapter.

If Then Else = Case The familiar if E1 then E2 else E3 is equivalent to case E1 of true => E2 | false => E3 Example: if x #”a” | false => #“b” (* note same types *)

Exceptions exception Foo and Bar; raise Foo; exception Foo of string; The handle clause matches exceptions with (hopefully) suitable actions Exceptions can be defined in let clauses

Polymorphic Functions If you don’t know the type in advance, or if it doesn’t matter, ‘a list matches a list of any type Example: fun listLen(x: ‘a list) = if x = nil then 0 else 1+listLen(tl(x));

Higher Order Functions Functions may be passed as parameters,e.g. fun trap(a,b,n,F)= if n <= 0 orelse b-a <= 0.0 then 0.0 else let val delta = (b-a)/real(n) in delta*(F(a)+F(a+delta))/2.0+ trap(a+delta,b,n-1,F) end;

Higher-Order Function map The map function map(F,[a 1,a 2,…,a n ]) produces the list [F(a 1 ),F(a 2 ),…,F(a n )] The function may be defined (per Harper’s new ML book) fun map f nil = nil | map f (h::t) = (f h)::(map f t)

Higher-Order Function reduce The reduce function reduce(F,[a 1,a 2,…,a n ]) produces F(a 1,F(a 2,F(…,F(a n-1, a n )…))) The reduce function may be implemented as follows (from Ullman) exception EmptyList; fun reduce (F, nil) = raise EmptyList | reduce (F, [a]) = a | reduce (F, x::xs) = F(x, reduce(F,xs));

More on reduce Harper gives a more general form of reduce fun reduce (unit, opn, nil) = unit | reduce (unit, opn, h::t) = opn(h, reduce (unit, opn, t)) Example: two ways to sum a list of numbers fun add_up nil = 0 | add_up(h::t) = h + add_up t or fun add_up alist = reduce (0, op +, alist) The op keyword allows + to be a parameter

More on reduce To avoid passing unit and opn as parameters that don’t change, again from Harper’s book, fun better_reduce (unit, opn, alist) = let fun red nil = unit | red (h::t) = opn(h, red t)) in red alist end We have less overhead by passing only those parameters that change

More on reduce “Staging” helps even more! Again from Harper fun staged_reduce (unit, opn) = let fun red nil = unit | red (h::t) = opn(h, red t)) in red end We can use staged_reduce on many lists, e.g. reduce(unit, opn, alist) is the same as (but slower than) staged_reduce(unit, opn) alist

Higher-Order Function filter The filter function takes a predicate P and a list [a 1,a 2,…,a n ] and returns the sublist such that P is true for every element of the sublist To implement filter fun filter(P, nil) = nil | filter(P, x::xs) = if P x then x::filter(P,xs) else filter(P,xs)

Chapter 6 Defining Your Own Types

The ML Type System Basic types include int, real, string, char, bool, and others Tuple types, e.g. int*real*char Function types, e.g. int->bool Type constructors list and option –int list –char option

Creating Names for Types type orderpair = int*int type finiteSequence = real list; and these can be parameterized

Datatypes Enumerated types, e.g. datatype berryType = raspberry | blueberry | blackberry; So then we can say, for example, val b:berryType = raspberry;

Recursive Datatypes Example: binary trees, where the values may be of some type ‘label: datatype ‘label btree = Empty | Node of ‘label * ‘label btree * ‘label btree val inBinary: int btree = Node(5,Node(1,Empty,Empty),Empty)

(* Sample ML program - Abstract Syntax Trees *) (* Assume that terminalType and nonterminalType already known *) (* Declare the ast datatype *) datatype ast = empty | leaf of terminalType | node of nonterminalType*(ast list); fun traverse(empty) = print "empty tree" | traverse(leaf(t)) = (printTerminal t; print " ") | traverse(node(nt, []) = printNonterminal(nt) | traverse(node(nt, x::xs)) = (printNonterminal(nt); traverse(x); traverseList(xs)) and fun traverseList([]) = print “ “ | traverseList(x::xs) = (traverse(x); traverseList(xs)); ASTs Revisited

Case Studies Binary search trees General trees

Chapter 7 More About ML Data Structures

Record Structures Records are wrapped in curly braces, and fields are separated by commas Field names may be used to refer to specific elements of the record

Record Example - type addressType = {street:string, city:string, zip:int}; type addressType = {city:string, street:string, zip:int} (note that SML sorted the fields alphabetically) - val umbc:addressType = {street="1000 Hilltop Circle", city="Baltimore",zip=21250}; val umbc = {city="Baltimore",street="1000 Hilltop Circle", zip=21250} : addressType - #city(umbc); val it = "Baltimore" : string

Pattern Matching in Records Pattern matching works, as in x as {street=xstr,city=xcity,zip=xzip}::xs If we don’t care about all the fields, use an ellipsis, e.g. x as {street=xstr,…}::xs Or even x as {city,…}

Arrays open Array; val zeroVector = array(100,0); sub(zeroVector,0) is zero, as is sub(zeroVector,99) update(zeroVector,2,3.14) changes the third element of the (now misnamed) zeroVector

References The statement val x = ref 0 makes a mutable binding !x is therefore zero The assignement operator := is defined only for reference types, e.g. x := 1

While Do We can use refs as loop iterators, e.g. val i = ref 0; while !i <= 10 do ( print(Int.toString(!I)); print(“ “); i:= !i + 1 ); Note use of dereference operator !

Case Studies Hash tables –Make an array of hash buckets, each bucket containing a simple list of values Triangularization of a matrix –If the array has m rows and n columns, make an array of m elements, each element being an array of n elements.

Chapter 8 Encapsulation and Modules

Structures Structures can contain function definitions, types, exceptions, constants, etc., e.g. structure hashTable = struct exception badSubscript; val nBuckets = 1024; type elementType = {key:string,…} type bucketType = elementType list fun lookup … end

The Mapping Structure structure Mapping = struct exception NotFound; val create = nil; fun lookup(d, nil) = raise NotFound | lookup(d,(e,r)::es) = (* code *) fun insert(d,r,nil) = [(d,r)] | insert(d,r,(e,s)::es) = (* code *) end; Note that the types of d, e and r need not be unspecified

Signatures Structures have corresponding signatures, which give the types of the structure elements A signature has the form sig end

A signature for string-int mappings signature SIMAPPING = sig exception NotFound; val create: (string*int) list; val insert: string * int * (string*int) list -> (string*int) list; val lookup: string*(string*int) list -> int end;

Making new Structures So, the declaration structure SiMapping:SIMAPPING = Mapping makes a new structure, with the same elements as Mapping, but with the types etc. specified in the SIMAPPING signature Does this remind you of anything?

Functors Study section 8.3 Do exercises and on page 281 Study section (a functor to create random number generators)

Chapter 9 Summary of the ML Standard Basis

Functions on primitive types int –negation ~, abs, real, chr real –negation ~, abs, floor, ceil, trunc, round

Functions on primitive types bool –not, andalso, orelse char –ord, str, implode string –print, explode, concat, size, substring –e.g. substring(“rectangles”,3,6) is “tangle”