Higher-Order Functions in Haskell

Slides:



Advertisements
Similar presentations
Introduction A function is called higher-order if it takes a function as an argument or returns a function as a result. twice :: (a  a)  a  a twice.
Advertisements

F28PL1 Programming Languages Lecture 14: Standard ML 4.
Comp 205: Comparative Programming Languages Higher-Order Functions Functions of functions Higher-order functions on lists Reuse Lecture notes, exercises,
CS 116 Tutorial 2 Functional Abstraction. Reminders Assignment 2 is due this Wednesday at Noon.
12 Haskell.  ftp://web.ntnu.edu.tw/WWW/func_prog/ghc zip ftp://web.ntnu.edu.tw/WWW/func_prog/ghc zip  Haskell is  Lazy evaluated  Case-sensitive.
Computer Science 112 Fundamentals of Programming II Finding Faster Algorithms.
0 PROGRAMMING IN HASKELL Chapter 7 - Higher-Order Functions.
Cse536 Functional Programming 1 7/14/2015 Lecture #2, Sept 29, 2004 Reading Assignments –Begin Chapter 2 of the Text Home work #1 can be found on the webpage,
0 PROGRAMMING IN HASKELL Typeclasses and higher order functions Based on lecture notes by Graham Hutton The book “Learn You a Haskell for Great Good” (and.
PrasadCS7761 Haskell Data Types/ADT/Modules Type/Class Hierarchy Lazy Functional Language.
Haskell. 2 GHC and HUGS Haskell 98 is the current version of Haskell GHC (Glasgow Haskell Compiler, version 7.4.1) is the version of Haskell I am using.
0 REVIEW OF HASKELL A lightening tour in 45 minutes.
0 PROGRAMMING IN HASKELL Chapter 7 - Defining Functions, List Comprehensions.
1-Nov-15 Haskell II Functions and patterns. Data Types Int + - * / ^ even odd Float + - * / ^ sin cos pi truncate Char ord chr isSpace isUpper … Bool.
Lee CSCE 314 TAMU 1 CSCE 314 Programming Languages Haskell: Higher-order Functions Dr. Hyunyoung Lee.
Lee CSCE 314 TAMU 1 CSCE 314 Programming Languages Haskell: More on Functions and List Comprehensions Dr. Hyunyoung Lee.
0 PROGRAMMING IN HASKELL Based on lecture notes by Graham Hutton The book “Learn You a Haskell for Great Good” (and a few other sources) Odds and Ends,
Recursion Higher Order Functions CSCE 314 Spring 2016.
Functional Programming Lecture 3 - Lists Muffy Calder.
Haskell Chapter 5, Part II. Topics  Review/More Higher Order Functions  Lambda functions  Folds.
Haskell. GHC and HUGS Haskell 98 is the current version of Haskell GHC (Glasgow Haskell Compiler, version 7.4.1) is the version of Haskell I am using.
Lecture 16: Advanced Topic: Functional Programming CS5363 Compiler and Programming Languages.
0 PROGRAMMING IN HASKELL Typeclasses and higher order functions Based on lecture notes by Graham Hutton The book “Learn You a Haskell for Great Good” (and.
6-Jul-16 Haskell II Functions and patterns. Data Types Int + - * / ^ even odd Float + - * / ^ sin cos pi truncate Char ord chr isSpace isUpper … Bool.
© M. Winter COSC 4P41 – Functional Programming Some functions id :: a -> a id x = x const :: a -> b -> a const k _ = k ($) :: (a -> b) -> a -> b.
Lecture 14: Advanced Topic: Functional Programming
Polymorphic Functions
Functional Programming
Conditional Expressions
Recursion.
Programming Languages
PROGRAMMING IN HASKELL
Types CSCE 314 Spring 2016.
dr Robert Kowalczyk WMiI UŁ
Theory of Computation Lecture 4: Programs and Computable Functions II
PROGRAMMING IN HASKELL
Fundamentals of Programming II Finding Faster Algorithms
Functions and patterns
A lightening tour in 45 minutes
Haskell Chapter 4.
More Functional Programming
Haskell.
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
6.001 SICP Data abstractions
PROGRAMMING IN HASKELL
Haskell Strings and Tuples
Computer Science 312 Haskell Lists 1.
PROGRAMMING IN HASKELL
Programming Languages
Higher Order Functions
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
CSCE 314: Programming Languages Dr. Dylan Shell
Pattern Matching Pattern matching allows us to do things like this:
Haskell Types, Classes, and Functions, Currying, and Polymorphism
Higher Order Functions
HIGHER ORDER FUNCTIONS
CSE 3302 Programming Languages
Records and Type Classes
Functions and patterns
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
Functions and patterns
Functional Programming
PROGRAMMING IN HASKELL
Lambda Expressions Cases
Laziness and Its Consequences
PROGRAMMING IN HASKELL
Presentation transcript:

Higher-Order Functions in Haskell Computer Science 312 Higher-Order Functions in Haskell 1

Convert a String to Uppercase import qualified Data.Char (toUpper) toUpper :: String -> String toUpper [] = [] toUpper (x:xs) = Data.Char.toUpper x : toUpper xs Transform a list of characters into another list of characters, by taking each character in the source list into an expression The pattern is head/tail recursion

Use a List Comprehension import qualified Data.Char (toUpper) toUpper :: String -> String toUpper [] = [] toUpper (x:xs) = Data.Char.toUpper x : toUpper xs import qualified Data.Char (toUpper) toUpper :: String -> String toUpper str = [Data.Char.toUpper ch | ch <- str] Expression Each character Source list

List Comprehensions Syntax: [<expression> | <item> <- <source list>] Read as “Take each item from a source list into an expression.” Prelude> [x ^ 2 | x <- [1..4]] [1, 4, 9, 16] Prelude> [sqrt x | x <- [4, 9, 16]] [2.0, 3.0, 4.0]

Can Also Use Pattern Matching Syntax: [<expression> | <pattern> <- <source list>] type StudentList = [(String, Float)] averageGPA :: StudentList -> Float averageGPA list = sum [gpa | (name, gpa) <- list] / length list Prelude> averageGPA [("Stan",3.56),("Ann",4.0),("Bill",2.95)] 3.503333333333333

Can Add Conditions for Filtering Syntax: [<expression> | <item> <- <source list>, <cond-1>, .., <cond-n>] Fetch all student names whose GPAs are >= 3.5 type StudentList = [(String, Float)] honorRoll :: StudentList -> [[Char]] honorRoll = [name | (name, gpa) <- list, gpa >= 3.5] Prelude> honorRoll [("Stan",3.56),("Ann",4.0),("Bill",2.95)] ["Stan","Ann"]

Quicksort in Python – 21 Lines def quicksort(lyst): quicksortHelper(lyst, 0, len(lyst) - 1) def quicksortHelper(lyst, left, right): if left < right: pivotLocation = partition(lyst, left, right) quicksortHelper(lyst, left, pivotLocation - 1) quicksortHelper(lyst, pivotLocation + 1, right) def partition(lyst, left, right): middle = (left + right) // 2 pivot = lyst[middle] lyst[middle] = lyst[right] lyst[right] = pivot boundary = left for index in range(left, right): if lyst[index] < pivot: swap(lyst, index, boundary) boundary += 1 swap (lyst, right, boundary) return boundary def swap(lyst, i, j): lyst[i], lyst[j] = lyst[j], lyst[i]

Quicksort in Haskell – 5 Lines quicksort :: Ord a => [a] -> [a] quicksort [] = [] quicksort (x:xs) = quicksort [y | y <- xs, y <= x] ++ [x] ++ quicksort [y | y <- xs, y > x] Select the head as the pivot item Shift the smaller items to its left Shift the larger items to its right Quicksort each of those lists Glue ‘em together around the pivot item

Three Ways to Transform a List roots :: Floating a => [a] -> [a] roots [] = [] roots (x:xs) = sqrt x : roots xs Head/tail recursion

Three Ways to Transform a List roots :: Floating a => [a] -> [a] roots [] = [] roots (x:xs) = sqrt x : roots xs Head/tail recursion List comprehension roots :: Floating a => [a] -> [a] roots list = [sqrt x | x <- list]

Three Ways to Transform a List roots :: Floating a => [a] -> [a] roots [] = [] roots (x:xs) = sqrt x : roots xs Head/tail recursion List comprehension roots :: Floating a => [a] -> [a] roots list = [sqrt x | x <- list] Map roots :: Floating a => [a] -> [a] roots list = map sqrt list

Map Hides (x:hs) Recursion roots :: Floating a => [a] -> [a] roots [] = [] roots (x:xs) = sqrt x : roots xs Head/tail recursion Generalize to a map by adding a function argument myMap :: (a -> b) -> [a] -> [b] myMap _ [] = [] myMap f (x:xs) = f x : myMap f xs Function types are expressed in parentheses in the signatures

lambda Expressions List comprehension Map with named function Prelude> [x ^ 2 | x <- [1..5]] [1,4,9,16,25] List comprehension Map with named function Prelude> map square [1..5] [1,4,9,16,25] Map with a lambda expression Prelude> map (\x -> x ^ 2) [1..5] [1,4,9,16,25] Syntax \<argument-1> .. <argument-n> -> <expression>

Filtering Head/tail recursion allEvens :: Integral a => [a] -> [a] allEvens [] = [] allEvens (x:xs) | even x = x : allEvens xs | otherwise = allEvens xs Head/tail recursion

Filtering Head/tail recursion List comprehension allEvens :: Integral a => [a] -> [a] allEvens [] = [] allEvens (x:xs) | even x = x : allEvens xs | otherwise = allEvens xs Head/tail recursion List comprehension allEvens :: Integral a => [a] -> [a] allEvens list = [x | x <- list, even x]

Filtering Head/tail recursion List comprehension Filter allEvens :: Integral a => [a] -> [a] allEvens [] = [] allEvens (x:xs) | even x = x : allEvens xs | otherwise = allEvens xs Head/tail recursion List comprehension allEvens :: Integral a => [a] -> [a] allEvens list = [x | x <- list, even x] allEvens :: Integral a => [a] -> [a] allEvens list = filter even list Filter

Filtering Head/tail recursion roots :: Floating a => [a] -> [a] roots [] = [] roots (x:xs) = sqrt x : roots xs Head/tail recursion Generalize to a filter by adding a predicate argument myFilter :: (a -> Bool) -> [a] -> [a] myFilter _ [] = [] myFilter p (x:xs) | p x = x : myFilter p xs | otherwise = myFilter p xs Example Prelude> filter (\x -> x `mod` 3 == 0) [1..27] [3,6,9,12,15,18,21,24,27]

Reducing a List to a Single Item Prelude> sum [1..10] 55 Prelude> product [1..10] 3628800

Reducing a List to a Single Item mySum :: Num a => [a] -> a mySum [x] = x mySum (x:xs) = x + mySum xs mySum [3, 5, 7] -> 3 + mySum [5, 7] -> 5 + mySum[7]-> <- 7 <- 12 <- 15 Computations move from right to left.

Reducing = Folding Reducing is called folding in Haskell. There are four flavors of folding: foldr1 – folds from the right, list must be nonempty foldr – folds from the right, list can be empty, must supply a base value foldl1 – folds from the left, list must be nonempty foldl – folds from the left, list can be empty, must supply a base value

Generalize: Folding from the Right mySum :: Num a => [a] -> a mySum [x] = x mySum (x:xs) = x + mySum xs A function of two args myFoldr1 :: (a -> a -> a) -> [a] -> a myFoldr1 _ [x] = x myFoldr1 f (x:xs) = f x (myFoldr1 f xs) There must be at least one item in the list!

Include the Empty List, Too myFoldr :: (a -> b -> b) -> b -> [a] -> b myFoldr _ baseValue [] = baseValue myFoldr f baseValue (x:xs) = f x (myFoldr f baseValue xs) mySum :: Num a => [a] -> a mySum list = myFoldr (+) 0 list myProduct :: Num a => [a] -> a myProduct list = myFoldr (*) 1 list

Folding from the Left myFoldl :: (b -> a -> b) -> b -> [a] -> b myFoldl _ baseValue [] = baseValue myFoldl f baseValue (x:xs) = myFoldl f (f x baseValue) xs myFoldl (+) 0 [3, 5, 7] -> myFoldl (+) 3 [5, 7] -> myFoldl (+) 8 [7] -> myFoldl(+) 15 [] -> <- 15

Tail Recursive, but Lazy! myFoldl :: (b -> a -> b) -> b -> [a] -> b myFoldl _ baseValue [] = baseValue myFoldl f baseValue (x:xs) = myFoldl f (f x baseValue) xs Haskell functions postpone evaluating arguments until they’re needed for computations (lazy evaluation) Thus, the evaluation of the second argument, the function application (f x baseValue), is postponed all the way down This requires extra overhead to track these calls

Exploiting laziness Currying Partial functions Infinite lists! For next time Exploiting laziness Currying Partial functions Infinite lists!