301AA - Advanced Programming

Similar documents
301AA - Advanced Programming [AP-2017]

Principles of Programming Languages

301AA - Advanced Programming [AP-2017]

Principles of Programming Languages

Principles of Programming Languages

CS 440: Programming Languages and Translators, Spring 2019 Mon

LECTURE 18. Control Flow

Introduction to Haskell

CS 457/557: Functional Languages

Higher Order Functions in Haskell

Standard prelude. Appendix A. A.1 Classes

(ii) Define a function ulh that takes a list xs, and pairs each element with all other elements in xs.

Logic - CM0845 Introduction to Haskell

INTRODUCTION TO HASKELL

PROGRAMMING IN HASKELL. CS Chapter 6 - Recursive Functions

10/21/08. Kathleen Fisher! Question:! Interesting answer in Algol:!

Introduction to Haskell

HIGHER-ORDER FUNCTIONS

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

Lecture 19: Functions, Types and Data Structures in Haskell

9/28/09. Kathleen Fisher. Question: Interesting answer in Algol:

Lecture 4: Higher Order Functions

An introduction introduction to functional functional programming programming using usin Haskell

Programming Languages Fall 2013

4/13/15. Kathleen Fisher for cs242 at Tufts Lightly edited with permission, Michelle Strout 4/10/15

EDAF40. 2nd June :00-19:00. WRITE ONLY ON ONE SIDE OF THE PAPER - the exams will be scanned in and only the front/ odd pages will be read.

COP4020 Programming Languages. Control Flow Prof. Robert van Engelen

Programming Languages 3. Definition and Proof by Induction

Principles of Programming Languages

n n Try tutorial on front page to get started! n spring13/ n Stack Overflow!

301AA - Advanced Programming [AP-2017]

Haskell Revision and Exercises

Functional Programming Mid-term exam Tuesday 3/10/2017

Shell CSCE 314 TAMU. Functions continued

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

Introduction to Functional Programming in Haskell 1 / 56

Lazy Functional Programming in Haskell

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

CITS3211 FUNCTIONAL PROGRAMMING. 6. Folding operators

CSCE 314 Programming Languages

Introduction to Haskell

A general introduction to Functional Programming using Haskell

Shell CSCE 314 TAMU. Higher Order Functions

Functional Programming - 2. Higher Order Functions

Haskell An Introduction

CS 320: Concepts of Programming Languages

CS 209 Functional Programming

Haskell Introduction Lists Other Structures Data Structures. Haskell Introduction. Mark Snyder

Functional Programming. Overview. Topics. Definition n-th Fibonacci Number. Graph

Advanced features of Functional Programming (Haskell)

Haskell: From Basic to Advanced. Part 3 A Deeper Look into Laziness

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

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

Haskell Overview III (3A) Young Won Lim 10/4/16

Exercise 1 ( = 24 points)

Programming Paradigms

Informatics 1 Functional Programming Lecture 11. Data Representation. Don Sannella University of Edinburgh

CSci 4223 Principles of Programming Languages

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

Functional Programming TDA 452, DIT 142

According to Larry Wall (designer of PERL): a language by geniuses! for geniuses. Lecture 7: Haskell. Haskell 98. Haskell (cont) - Type-safe!

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

CS 360: Programming Languages Lecture 10: Introduction to Haskell

CSc 372 Comparative Programming Languages

Informatics 1 Functional Programming Lecture 12. Data Abstraction. Don Sannella University of Edinburgh

Lecture 5: Lazy Evaluation and Infinite Data Structures

CSc 372. Comparative Programming Languages. 8 : Haskell Function Examples. Department of Computer Science University of Arizona

Informatics 1 Functional Programming Lecture 7. Map, filter, fold. Don Sannella University of Edinburgh

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

CSE 3302 Programming Languages Lecture 8: Functional Programming

Principles of Programming Languages

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

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

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

Tree Oriented Programming. Jeroen Fokker

Tentamen Functioneel Programmeren 2001 Informatica, Universiteit Utrecht Docent: Wishnu Prasetya

It is better to have 100 functions operate one one data structure, than 10 functions on 10 data structures. A. Perlis

Programming Language Concepts, CS2104 Lecture 7

Functional Programming and Haskell

Applicative, traversable, foldable

Practical Haskell. An introduction to functional programming. July 21, Practical Haskell. Juan Pedro Villa-Isaza. Introduction.

Haskell: From Basic to Advanced. Part 2 Type Classes, Laziness, IO, Modules

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

Functional Programming TDA 452, DIT 142

A tour of the Haskell Prelude

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

Applicative, traversable, foldable

The type checker will complain that the two branches have different types, one is string and the other is int

CS 11 Haskell track: lecture 1

Haskell & functional programming, some slightly more advanced stuff. Matteo Pradella

Haskell 101. (Version 1 (July 18, 2012)) Juan Pedro Villa Isaza

CS 320: Concepts of Programming Languages

Software System Design and Implementation

Programming with Math and Logic

Recursion and Induction: Haskell; Primitive Data Types; Writing Function Definitions

Programming in Omega Part 1. Tim Sheard Portland State University

Some Advanced ML Features

Haskell Types COMP360

Streams and Evalutation Strategies

CS 340 Spring 2019 Midterm Exam

Transcription:

301AA - Advanced Programming Lecturer: Andrea Corradini andrea@di.unipi.it h;p://pages.di.unipi.it/corradini/ Course pages: h;p://pages.di.unipi.it/corradini/dida@ca/ap-18/ AP-2018-19: Algebraic Datatypes and Higher Order Func8ons

Datatype DeclaraDons Examples data Color = Red Yellow Blue elements are Red, Yellow, Blue data Atom = Atom String Number Int elements are Atom A, Atom B,, Number 0,... data List = Nil Cons (Atom, List) elements are Nil, Cons(Atom A, Nil), Cons(Number 2, Cons(Atom( Bill ), Nil)),... General form data <name> = <clause> <clause> <clause> ::= <constructor> <contructor> <type> Type name and constructors must be Capitalized. 2

Datatypes and Pa;ern Matching Recursively defined data structure data Tree = Leaf Int Node (Int, Tree, Tree) Node(4, Node(3, Leaf 1, Leaf 2), Node(5, Leaf 6, Leaf 7)) 4 Constructors can be used in Pa;ern Matching Recursive funcdon 1 3 2 6 5 7 sum (Leaf n) = n sum (Node(n,t1,t2)) = n + sum(t1) + sum(t2) 3

Case Expression Datatype data Exp = Var Int Const Int Plus (Exp, Exp) Case expression case e of Var n -> Const n -> Plus(e1,e2) -> IndentaDon ma;ers in case statements in Haskell. 4

FuncDon Types in Haskell In Haskell, f :: A -> B means for every x A, f(x) = some element y = f(x) B run forever In words, if f(x) terminates, then f(x) B. In ML, funcdons with type A B can throw an excepdon or have other effects, but not in Haskell Prelude> :t not -- type of some predefined functions not :: Bool -> Bool Prelude> :t (+) (+) :: Num a => a -> a -> a Note: if f is a standard Prelude> :t (:) binary func4on, `f` is its (:) :: a -> [a] -> [a] infix version Prelude> :t elem If x is an infix (binary) elem :: Eq a => a -> [a] -> Bool operator, (x) is its prefix version. 5

From loops to recursion In funcdonal programming, for and while loops are replaced by using recursion Recursion: subroudnes call themselves directly or indirectly (mutual recursion) length' [] = 0 length' (x:s) = 1 + length'(s) // definition using guards and pattern matching take' :: (Num i, Ord i) => i -> [a] -> [a] take' n _ n <= 0 = [] take' _ [] = [] take' n (x:xs) = x : take' (n-1) xs 6

Higher-Order FuncDons FuncDons that take other funcdons as arguments or return a funcdon as a result are higher-order func4ons. Pervasive in funcdonal programming applyto5 :: Num t1 => (t1 -> t2) -> t2 -- function as arg applyto5 f = f 5 > applyto5 succ => 6 Ø applyto5 (7 +) => 12 applytwice :: (a -> a) -> a -> a -- function as arg and res applytwice f x = f (f x) > applytwice (+3) 10 => 16 > applytwice (++ " HAHA") "HEY" => "HEY HAHA HAHA" > applytwice (3:) [1] => [3,3,1] 7

Higher-Order FuncDons Can be used to support alternadve syntax Example: From funcdonal to stream-like ( >) :: t1 -> (t1 -> t2) -> t2 ( >) a f = f a > length ( tail ( reverse [1,2,3])) => 2 > [1,2,3] > reverse > tail > length => 2 8

Higher-Order FuncDons everywhere Any curried funcdon with more than one argument is higher-order: applied to one argument it returns a funcdon (+) :: Num a => a -> a -> a > let f = (+) 5 // partial application >:t f ==> f :: Num a => a -> a > f 4 ==> 9 elem :: (Eq a, Foldable t) => a -> t a -> Bool > let isupper = (`elem` ['A'..'Z']) >:t isupper ==> isupper :: Char -> Bool > isupper 'A' ==> True > isupper '0' ==> False 9

Higher-Order FuncDons: the map combinator map: applies argument funcdon to each element in a collecdon. map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = f x : map f xs > map (+3) [1,5,3,1,6] [4,8,6,4,9] > map (++ "!") ["BIFF", "BANG", "POW"] ["BIFF!","BANG!","POW!"] > map (replicate 3) [3..6] [[3,3,3],[4,4,4],[5,5,5],[6,6,6]] > map (map (^2)) [[1,2],[3,4,5,6],[7,8]] [[1,4],[9,16,25,36],[49,64]] > map fst [(1,2),(3,5),(6,3),(2,6),(2,5)] [1,3,6,2,2] 10

Higher-Order FuncDons: the filter combinator filter: takes a collecdon and a boolean predicate, and returns the collecdon of the elements sadsfying the predicate filter :: (a -> Bool) -> [a] -> [a] filter _ [] = [] filter p (x:xs) p x = x : filter p xs otherwise = filter p xs > filter (>3) [1,5,3,2,1,6,4,3,2,1] [5,6,4] > filter (==3) [1,2,3,4,5] [3] > filter even [1..10] [2,4,6,8,10] > let notnull x = not (null x) in filter notnull [[1,2,3],[],[3,4,5],[2,2],[],[],[]] [[1,2,3],[3,4,5],[2,2]] 11

Higher-Order FuncDons: the reduce combinator reduce (foldl, foldr): takes a collecdon, an inidal value, and a funcdon, and combines the elements in the collecdon according to the funcdon. -- folds values from end to beginning of list foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b foldr f z [] = z foldr f z (x:xs) = f x (foldr f z xs) -- folds values from beginning to end of list foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b foldl f z [] = z foldl f z (x:xs) = foldl f (f z x) xs -- variants for non-empty lists foldr1 :: Foldable t => (a -> a -> a) -> t a -> a foldl1 :: Foldable t => (a -> a -> a) -> t a -> a Binary funcdon IniDal value List/ collecdon 12

Examples foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b foldr1 :: Foldable t => (a -> a -> a) -> t a -> a sum' :: (Num a) => [a] -> a sum' xs = foldl (\acc x -> acc + x) 0 xs maximum' :: (Ord a) => [a] -> a maximum' = foldr1 (\x acc -> if x > acc then x else acc) reverse' :: [a] -> [a] reverse' = foldl (\acc x -> x : acc) [] product' :: (Num a) => [a] -> a product' = foldr1 (*) filter' :: (a -> Bool) -> [a] -> [a] filter' p = foldr (\x acc > if p x then x : acc else acc) [] head' :: [a] -> a head' = foldr1 (\x _ -> x) last' :: [a] -> a last' = foldl1 (\_ x -> x) 13

On efficiency IteraDon and recursion are equally powerful in theoredcal sense: IteraDon can be expressed by recursion and vice versa Recursion is the natural soludon when the soludon of a problem is defined in terms of simpler versions of the same problem, as for tree traversal In general a procedure call is much more expensive than a condidonal branch Thus recursion is in general less efficient, but good compilers for funcdonal languages can perform good code opdmizadon Use of combinators, like map, reduce (foldl, foldr), filter, foreach, strongly encouraged, because they are highly opdmized by the compiler. 14

Tail-Recursive FuncDons Tail-recursive func:ons are funcdons in which no operadons follow the recursive call(s) in the funcdon, thus the funcdon returns immediately aier the recursive call: tail-recursive not tail-recursive int trfun() int rfun() { { return trfun(); return 1+rfun(); } } A tail-recursive call could reuse the subroudne's frame on the run-dme stack, since the current subroudne state is no longer needed Simply eliminadng the push (and pop) of the next frame will do In addidon, we can do more for tail-recursion op:miza:on: the compiler replaces tail-recursive calls by jumps to the beginning of the funcdon 15

Tail-Recursion OpDmizaDon: Example int gcd(int a, int b) // tail recursive { if (a==b) return a; else if (a>b) return gcd(a-b, b); else return gcd(a, b-a); } int gcd(int a, int b) // possible optimization { start: if (a==b) return a; else if (a>b) { a = a-b; goto start; } else { b = b-a; goto start; } } int gcd(int a, int b) // comparable efficiency { while (a!=b) if (a>b) a = a-b; else b = b-a; return a; } 16

Tail-Call OpDmizaDon Tail-call: a funcdon returns calling another funcdon, not necessarily itself OpDmizaDon sdll possible, reusing the stack frame Note: Number/size of parameters can differ Stack with tail-call opdmizadon 17

ConverDng Recursive FuncDons to Tail-Recursive FuncDons Remove the work after the recursive call and include it in some other form as a computation that is passed to the recursive call For example reverse [] = [] -- quadratic reverse (x:xs) = (reverse xs) ++ [x] can be rewritten into a tail-recursive function: reverse xs = -- linear, tail recursive let rev ( [], accum ) = accum rev ( y:ys, accum ) = rev ( ys, y:accum ) in rev ( xs, [] ) Equivalently, using the where syntax: reverse xs = -- linear, tail recursive rev ( xs, [] ) where rev ( [], accum ) = accum rev ( y:ys, accum ) = rev ( ys, y:accum ) 18

ConverDng Recursive FuncDons to Tail-Recursive FuncDons Another example: the non-tail-recursive function computing summation = \(f, low, high) -> if (low == high) then (f low) else (f low) + summation (f, low + 1, high) high n=low f (n) can be rewritten into a tail-recursive function: summationtr = \(f, low, high, subtotal) -> if (low == high) then subtotal + (f low) else summationtr (f, low + 1, high, subtotal + (f low)) 19

ConverDng recursion into tail recursion: Fibonacci The Fibonacci function implemented as a recursive function is very inefficient as it takes exponential time to compute: fib = \n -> if n == 0 then 1 else if n == 1 then 1 else fib (n - 1) + fib (n - 2) with a tail-recursive helper function, we can run it in O(n) time: fibtr = \n -> let fibhelper (f1, f2, i) = if (n == i) then f2 else fibhelper (f2, f1 + f2, i + 1) in fibhelper(0,1,0) 20

Comparing foldl and foldr -- folds values from end to beginning of list foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b foldr f z [] = z foldr f z (x:xs) = f x (foldr f z xs) -- folds values from beginning to end of list foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b foldl f z [] = z foldl f z (x:xs) = foldl f (f z x) xs 21

From imperadve to funcdonal programming Searching a substring: Java code static int indexof(char[] source, int sourceoffset, int sourcecount, char[] target, int targetoffset, int targetcount, int fromindex) { char first = target[targetoffset]; int max = sourceoffset + (sourcecount - targetcount); for (int i = sourceoffset + fromindex; i <= max; i++) { /* Look for first character. */ if (source[i]!= first) { while (++i <= max && source[i]!= first); } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetcount - 1; for (int k = targetoffset + 1; j < end && source[j] == target[k]; j++, k++); } if (j == end) { /* Found whole string. */ return i - sourceoffset; } } } return -1; 22

Searching a Substring: ExploiDng Laziness isprefixof :: Eq a => [a] -> [a] -> Bool -- returns True if first list is prefix of the second isprefixof [] x = True isprefixof (y:ys) [] = False isprefixof (y:ys)(x:xs) = if (x == y) then isprefixof ys xs else False suffixes:: [a]-> [[a]] -- All suffixes of s suffixes[] = [[]] suffixes(x:xs) = (x:xs) : suffixes xs or :: [Bool] -> Bool -- (or bs) returns True if any of the bs is True or [] = False or (b:bs) = b or bs issubstring :: [a] -> [a] -> Bool x `issubstring` s = or [ x `isprefixof` t t <- suffixes s ] 23