List Processing in Ocaml

Similar documents
List Processing in SML

List Processing in SML

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Haskell Functions

PROGRAMMING IN HASKELL. CS Chapter 6 - Recursive Functions

CS 321 Programming Languages

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

List Functions, and Higher-Order Functions

FOFL and FOBS: First-Order Functions

Shell CSCE 314 TAMU. Functions continued

02157 Functional Programming Tagged values and Higher-order list functions

Lists. Michael P. Fourman. February 2, 2010

PROGRAMMING IN HASKELL. Chapter 5 - List Comprehensions

CS 457/557: Functional Languages

Tuples. CMSC 330: Organization of Programming Languages. Examples With Tuples. Another Example

02157 Functional Programming. Michael R. Ha. Tagged values and Higher-order list functions. Michael R. Hansen

SNU Programming Language Theory

Introduc)on To Standard ML

Haske k ll An introduction to Functional functional programming using Haskell Purely Lazy Example: QuickSort in Java Example: QuickSort in Haskell

An introduction introduction to functional functional programming programming using usin Haskell

Problem Set CVO 103, Spring 2018

CMSC 330, Fall 2013, Practice Problems 3

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Fall 2011

Problem Set 1 Due: 11:59pm Wednesday, February 7

A general introduction to Functional Programming using Haskell

CSCI-GA Scripting Languages

Shell CSCE 314 TAMU. Haskell Functions

The List Datatype. CSc 372. Comparative Programming Languages. 6 : Haskell Lists. Department of Computer Science University of Arizona

F28PL1 Programming Languages. Lecture 14: Standard ML 4

02157 Functional Programming Lecture 2: Functions, Basic Types and Tuples

School of Computer Science

Lecture 19: Functions, Types and Data Structures in Haskell

02157 Functional Programming. Michael R. Ha. Lecture 2: Functions, Types and Lists. Michael R. Hansen

CMSC 330: Organization of Programming Languages. OCaml Higher Order Functions

Topic 5: Examples and higher-order functions

CMSC 330: Organization of Programming Languages. OCaml Higher Order Functions

CMSC 330: Organization of Programming Languages. OCaml Higher Order Functions

Lab 7: OCaml 12:00 PM, Oct 22, 2017

02157 Functional Programming Lecture 3: Lists

Programming Languages and Techniques (CIS120)

Tail Calls. CMSC 330: Organization of Programming Languages. Tail Recursion. Tail Recursion (cont d) Names and Binding. Tail Recursion (cont d)

Programming Language Concepts: Lecture 14

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

Lists. Prof. Clarkson Fall Today s music: "Blank Space" by Taylor Swift

CSE341 Spring 2017, Midterm Examination April 28, 2017

Part I: Written Problems

Functional Programming. Pure Functional Programming

Handout 2 August 25, 2008

Case by Case. Chapter 3

CSE 341 Sample Midterm #2

Haskell Overview II (2A) Young Won Lim 9/26/16

02157 Functional Programming. Michael R. Ha. Disjoint Unions and Higher-order list functions. Michael R. Hansen

CSE341 Autumn 2017, Midterm Examination October 30, 2017

Chapter 3 Linear Structures: Lists

Background. CMSC 330: Organization of Programming Languages. Useful Information on OCaml language. Dialects of ML. ML (Meta Language) Standard ML

CSE341 Spring 2016, Midterm Examination April 29, 2016

Haskell Overview II (2A) Young Won Lim 8/23/16

Haskell Overview II (2A) Young Won Lim 8/9/16

CSE 130: Programming Languages. Polymorphism. Ranjit Jhala UC San Diego

Wellesley College CS251 Programming Languages Spring, 2000 FINAL EXAM REVIEW PROBLEM SOLUTIONS

F# - LISTS. In this method, you just specify a semicolon-delimited sequence of values in square brackets. For example

COSE212: Programming Languages. Lecture 4 Recursive and Higher-Order Programming

CS301 Compiler Design and Implementation Handout # 18 Prof. Lyn Turbak February 19, 2003 Wellesley College

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

Typed Racket: Racket with Static Types

Chapter 3 Linear Structures: Lists

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

Programming Languages and Techniques (CIS120)

Thinking Induc,vely. COS 326 David Walker Princeton University

Sum-of-Product (SOP) Datatypes in SML

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Winter 2013

CSCI-GA Final Exam

Introduction to Haskell

Booleans (aka Truth Values) Programming Languages and Compilers (CS 421) Booleans and Short-Circuit Evaluation. Tuples as Values.

CS251 Programming Languages Handout # 29 Prof. Lyn Turbak March 7, 2007 Wellesley College

CMSC 330, Fall 2013, Practice Problem 3 Solutions

CIS 120 Midterm I February 16, 2015 SOLUTIONS

Lists. Adrian Groza. Department of Computer Science Technical University of Cluj-Napoca

CS 320: Concepts of Programming Languages

CMSC330 Fall 2016 Midterm #1 2:00pm/3:30pm

CSE341 Spring 2016, Midterm Examination April 29, 2016

Functional Programming and Haskell

CS 360: Programming Languages Lecture 12: More Haskell

Programming Languages 3. Definition and Proof by Induction

Functional Programming Languages (FPL)

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

The Typed Racket Guide

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

CSc 520 Principles of Programming Languages. Currying Revisited... Currying Revisited. 16: Haskell Higher-Order Functions

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

CSE341, Fall 2011, Midterm Examination October 31, 2011

CSc 372. Comparative Programming Languages. 11 : Haskell Higher-Order Functions. Department of Computer Science University of Arizona

Principles of Programming Languages

Problem Set 3 Due: 11:59 pm on Thursday, September 25

Hofl, a Higher-order Functional Language. 1 An Overview of Hofl. 2 Abstractions and Function Applications

Sum-of-Product Data Types

Haskell 98 in short! CPSC 449 Principles of Programming Languages

COSE212: Programming Languages. Lecture 3 Functional Programming in OCaml

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

Types and Type Inference

Transcription:

CS251 Programming Languages Handout # 14 Prof. Lyn Turbak February 2, 2007 Wellesley College List Processing in Ocaml Given a list of integers ns, suppose we want to return a new list of the same length in which each element is one more than the corresponding element of ns. ohere s one way to express this in Java (using the IntList class you ve seen in CS111 and CS230). public static IntList inclist (IntList ns) { if (IntList.isEmpty(ns)) { return IntList.empty(); } else { return IntList.prepend(1 + IntList.head(ns), inclist(intlist.tails(ns))); } } What are the corresponding list manipulation operators in Ocaml? Java Ocaml empty() [] prepend(x,ys) x::ys head(xs) List.hd(xs) tail(xs) List.tl(xs) isempty(xs) xs = [] In Ocaml, [E 1 ;E 2 ;...;E n ] is syntactic sugar for E 1 ::E 2 ::...::E n ::[]. E.g., we can use this sugar to express a list of the first four positive integers as [1;2;3;4]. Here is an Ocaml transliteration of the Java inclist given above: let rec inclist ns = if ns = [] then [] else (1+List.hd(ns))::(incList (List.tl ns)) However, in practice, List.hd and List.tl are rarely used to process lists in Ocaml. Instead, we normally use Ocaml s powerful pattern matching facility (the match... with construct) to perform a case analysis on a list: let rec inclist ns = match ns with [] -> [] n::ns -> (n+1)::(inclist ns ) The expression between match and with (ns in this case) is called the discriminant. Following with is a sequence of clauses of the form pattern -> body. The value of the discriminant is compared against the pattern of each clause in the sequence until a match is found. The body of the matching clause is then evaluated in a context that uses the names bound by the patternmatching process. The result of evaluating the body is returned as the value of the match expression. In the inclist example, the clause [] -> [] means if ns is the empty list, then return the empty list. The clause n::ns -> (n+1)::(inclist ns ) means if ns is a non-empty list whose head is n and whose tail is ns, then return the list that results from prepending n+1 to the result of recursively processing ns. The following process function is a contrived example to illustrate pattern matching: 1

let rec process ps = match ps with [(c,d);(e,f)] -> [(d,f);(c,e)] p1::p2::p3::ps -> p3::(process(p1::p2::ps )) _ -> ps The underscore pattern, _, is a special pattern that matches anything without binding the underscore symbol to a value. Here are some sample uses of process: # process [];; - : ( a * a) list = [] # process [(1,2)];; - : (int * int) list = [(1, 2)] # process [(1,2);(3,4)];; - : (int * int) list = [(2, 4); (1, 3)] # process [(1,2);(3,4);(5,6)];; - : (int * int) list = [(5, 6); (2, 4); (1, 3)] # process [(1,2);(3,4);(5,6);(7,8)];; - : (int * int) list = [(5, 6); (7, 8); (2, 4); (1, 3)] Patterns cannot contain duplicates, but can have when guards: let condswap xs = match xs with x1::x2::x3::xs when x1 = x3 -> x2 :: x1 :: x3 :: xs _ -> xs;; # condswap [1;2;1;4];; - : int list = [2; 1; 1; 4] # condswap [1;2;3;4];; - : int list = [1; 2; 3; 4] Subpatterns can be named by as patterns: let condswap xs = match xs with x1::x2::((x3::_) as xs ) when x1 = x3 -> x2 :: x1 :: xs _ -> xs;; val condswap : a list -> a list = <fun> 2

In class, we will write the following functions: val sum : int list -> int sum ns returns the sum of all the integers in a list of integers ns. # sum [];; - : int = 0 # sum [3];; - : int = 3 # sum [3;2;7;5];; - : int = 17 val range : int * int -> int list range (lo, hi) returns a list of integers from lo up to hi, inclusive. The list is empty if lo > hi. # range (3,7);; - : int list = [3; 4; 5; 6; 7] # range (5,5);; - : int list = [5] # range (6,5);; - : int list = [] 3

val squares : int list -> int list squares ns returns a list of the squares of the corresponding integers in the list ns. # squares [3;1;5;4;2];; - : int list = [9; 1; 25; 16; 4] # squares [3];; - : int list = [9] # squares [];; - : int list = [] val evens : int list -> int list evens ns returns a list of the even integers in the list ns in the same relative order that they appear in ns. (x mod y gives the remainder of dividing the integer x by the integer y.) # evens [3;1;4;2;5;8;9;6];; - : int list = [4; 2; 8; 6] # evens [3;1;5;9];; - : int list = [] # evens [6;256;100];; - : int list = [6; 256; 100] # evens [];; - : int list = [] Note: A key benefit of defining list-processing functions like sum, range, squares, evens is that they can be easily composed in mix-and-match ways to solve more complex problems. For example: let sumofsquaredevensbetween (lo,hi) = sum(squares(evens(range(lo,hi)))) 4

val remove : a * a list -> a list remove (x, ys) returns a list of all the elements in ys except for occurrences of x. The relative order of non-x elements is preserved. # remove (5, [5;4;5;3;4;2;3;4;5;1;3;5;4;2;5]);; - : int list = [4; 3; 4; 2; 3; 4; 1; 3; 4; 2] # remove (5, [1;2;3;4]);; - : int list = [1; 2; 3; 4] # remove (5, []);; - : int list = [] val ismember : a * a list -> bool ismember(x,ys) returns true if x is an element of the list ys (as determined by =) and false otherwise. # ismember(3,[5;2;3;1;4]);; # ismember(6,[5;2;3;1;4]);; # ismember("be",["to";"be";"or";"not";"to";"be"]);; # ismember("two",["to";"be";"or";"not";"to";"be"]);; # ismember((2,"two"), [(3,"three");(1,"one");(2,"two");(4,"four")]);; # ismember((2,"too"), [(3,"three");(1,"one");(2,"two");(4,"four")]);; 5

val removedups : a list -> a list removedups xs returns a list containing one occurrence of each element in xs. The order of elements in the returned list is unspecified. Note: There are many ways to define this function! # removedups [5;4;5;3;4;2;3;4;5;1;3;5;4;2;5];; - : int list = [1; 3; 4; 2; 5] (* order doesn t matter *) # removedups ["do";"be";"do";"be";"do"];; - : string list = ["be"; "do"] (* order doesn t matter *) # removedups [ a ; b ; r ; a ; c ; a ; d ; a ; b ; r ; a ];; - : char list = [ c ; d ; b ; r ; a ] (* order doesn t matter *) # removedups [];; - : _a list = [] 6

val issorted : a list -> bool issorted xs returns true if the list xs is sorted from low to high according to <=, and false otherwise. # issorted [];; # issorted [3];; # issorted [3;1;4;2];; # issorted [1;2;3;4];; # issorted [false;true];; # issorted [true;false];; # issorted [ a ; b ; c ];; # issorted [ c ; a ; b ];; # issorted ["one";"two";"three"];; # issorted ["one";"three";"two"];; # issorted [(1,"bar");(2,"baz");(3,"foo")];; # issorted [(1,"bar");(3,"baz");(2,"foo")];; # issorted [(1,"foo");(2,"bar");(3,"baz")];; # issorted [[];[1];[1;2];[1;3;2];[1;3;4];[1;4];[2]];; # issorted [[];[1];[1;2;3];[1;2];[1;3;4];[1;4];[2]];; 7

val flatten : a list list -> a list flatten xss returns a list containing all of the elements of the lists in the list of list xss in the same order. Use the infix @ operator or prefix List.append operator to append two lists. Note: The flatten function is called List.flatten in the Ocaml standard library. # flatten [[4;2];[3;1;5;8];[7];[6;0;9]];; - : int list = [4; 2; 3; 1; 5; 8; 7; 6; 0; 9] # flatten [["foo"];["bar";"baz"];["quux"]];; - : string list = ["foo"; "bar"; "baz"; "quux"] # flatten [["foo"]];; - : string list = ["foo"] # flatten [];; - : a list = [] val reverse : a list -> a list reverse xs returns a list containing the elements of the list xs in reverse order. Note: This function is called List.rev in the Ocaml standard library. # reverse [3;1;5;4;2];; - : int list = [2; 4; 5; 1; 3] # reverse ["foo";"bar";"baz"];; - : string list = ["baz"; "bar"; "foo"] # reverse ["foo"];; - : string list = ["foo"] # reverse [];; - : a list = [] 8

val zip : a list * b list -> ( a * b) list zip (xs,ys) returns a list of pairs containing the corresponding elements of the lists xs and ys. The length of the resulting list is the length of the shorter of xs and ys. Note: A curried version of this function is called List.combine in the Ocaml standard library.. # zip ([1;2;3],[ a ; b ; c ]);; - : (int * char) list = [(1, a ); (2, b ); (3, c )] # zip ([1;2;3;4;5],[ a ; b ; c ]);; - : (int * char) list = [(1, a ); (2, b ); (3, c )] # zip ([1;2;3],[ a ; b ; c ; d ; e ]);; - : (int * char) list = [(1, a ); (2, b ); (3, c )] # zip ([],[ a ; b ; c ]);; - : ( a * char) list = [] # zip ([1;2;3],[]);; - : (int * a) list = [] val unzip : ( a * b) list -> a list * b list unzip ps takes a list of pairs ps and returns a pair of lists, the first of which contains all the first components of ps, and the second of which contains all the second components of ps. Note: This function is called List.split in the Ocaml standard library. # unzip [(1, a ); (2, b ); (3, c )];; - : int list * char list = ([1; 2; 3], [ a ; b ; c ]) # unzip [(2, b )];; - : int list * char list = ([2], [ b ]) # unzip [];; - : a list * b list = ([], []) 9

val mapcons : a * a list list -> a list list mapcons (x,zss) returns a list containing the result of prepending x to each list in the list of lists zss. # mapcons (5,[[4;1];[3];[2;1;3];[]]);; - : int list list = [[5; 4; 1]; [5; 3]; [5; 2; 1; 3]; [5]] # mapcons ("foo", [[]]);; - : string list list = [["foo"]] # mapcons ("foo", []);; - : string list list = [] val subsets : a list -> a list list Assume that xs is a list without duplicates, and thus represents a set of elements. subsets xs returns a list of lists containing all subsets of xs. The elements of each subset must appear in the same relative order as in xs, but the order of the subsets themselves is unspecified. Hint: mapcons is helpful here. # subsets [];; - : _a list list = [[]] # subsets [4];; - : int list list = [[]; [4]] # subsets [3;4];; - : int list list = [[]; [4]; [3]; [3; 4]] # subsets [2;3;4];; - : int list list = [[]; [4]; [3]; [3; 4]; [2]; [2; 4]; [2; 3]; [2; 3; 4]] # subsets [1;2;3;4];; - : int list list = [[]; [4]; [3]; [3; 4]; [2]; [2; 4]; [2; 3]; [2; 3; 4]; [1]; [1; 4]; [1; 3]; [1; 3; 4]; [1; 2]; [1; 2; 4]; [1; 2; 3]; [1; 2; 3; 4]] # subsets [ a ; b ; c ; d ];; - : char list list = [[]; [ d ]; [ c ]; [ c ; d ]; [ b ]; [ b ; d ]; [ b ; c ]; [ b ; c ; d ]; [ a ]; [ a ; d ]; [ a ; c ]; [ a ; c ; d ]; [ a ; b ]; [ a ; b ; d ]; [ a ; b ; c ]; [ a ; b ; c ; d ]] 10

val decimal : int list -> int Assume that bs is a list of zeroes and ones. decimal bs returns an integer that is the decimal representation of the number represented in binary by bs. An empty list of bits is assumed to denote 0. # decimal [];; - : int = 0 # decimal [0];; - : int = 0 # decimal [1];; - : int = 1 # decimal [1;0];; - : int = 2 # decimal [1;0;0];; - : int = 4 # decimal [1;0;1];; - : int = 5 # decimal [1;0;1;0];; - : int = 10 # decimal [1;0;1;1];; - : int = 11 # decimal [1;0;1;1;0];; - : int = 22 # decimal [1;0;1;1;1];; - : int = 23 # decimal [1;0;1;1;1;0];; - : int = 46 11