Exploring Languages
with Interpreters
and Functional Programming

Chapter 18
More List Processing

H. Conrad Cunningham

19 October 2018

Copyright (C) 2018, H. Conrad Cunningham

Acknowledgements: I originally created these slides in Fall 2018 to accompany what is now Chapter 18, More List Processing, in the 2018 version of the textbook Exploring Languages with Interpreters and Functional Programming.

Browser Advisory: The HTML version of this document may require use of a browser that supports the display of MathML. A good choice as of October 2018 is a recent version of Firefox from Mozilla.

Source Code: The Haskell module for this chapter is in MoreLists.hs.

More List Processing

Lecture Goals

Arithmetic Sequences (1)

Arithmetic Sequences (2)

Arithmetic Sequences (3)

Geometric Sequence

geometric :: (Ord a, Num a) => a -> a -> a -> [a]
geometric r m n | m > n     = []
                | otherwise = m : geometric r (m*r) n

geometric 2 1 10 \Longrightarrow [1,2,4,8]

List Comprehension

Syntax: [ expression | qualifiers ]

Qualifier: Generator

Syntax: pat <- exp

Qualifier: Filter

Syntax: Any Boolean expression

Qualifier: Local Definition

Syntax: let pat = expr

Multiple Qualifiers (1)

Multiple Qualifiers (2)

Multiple Qualifiers (3)

Translating Comprehensions

Translated to regular functions calls — see section 18.3.2

Underlying higher-order function concatMap — which can represent both map and filter

Strings of Spaces

spaces :: Int -> String
spaces n = [ ' ' | i<-[1..n] ]

When n < 1 yields empty string

Prime Number Test

isPrime :: Int -> Bool
isPrime n | n > 1 = (factors n == [])
    where factors m = [ x | x<-[2..(m-1)], m `mod` x == 0 ]
isPrime   _       =  False

n prime if n > 1 and has no factors other than 1 and n

Lazy evaluation, so factors never generates more than 1 element

Squares of Primes

sqPrimes :: Int -> Int -> [Int]
sqPrimes m n = [ x*x | x<-[m..n], isPrime x ]
sqPrimes' :: Int -> Int -> [Int]
sqPrimes' m n = map (\x -> x*x) (filter isPrime [m..n])

Doubling Positive Elements

doublePos5 :: [Int] -> [Int]
doublePos5 xs = [ 2*x | x <- xs, 0 < x ]

Concatenating List of Lists of Lists

superConcat :: [[[a]]] -> [a]
superConcat xsss = [ x | xss<-xsss, xs<-xss, x<-xs ]
superConcat' :: [[[a]]] -> [a]
superConcat' = concat . map concat

First Occurrence (1)

Consider: position takes list and value, returns position of first occurrence; 0 if not in list

Strategy:
Solve a more general problem first, then use it to get the specific solution desired.

Generalize to finding all occurrences

First Occurrence (2)

Generalize to finding all occurrences

    positions :: Eq a => [a] -> a -> [Int]
    positions xs x = [ i | (i,y)<-zip [1..length xs] xs, x == y]
    position :: Eq a => [a] -> a -> Int 
    position xs x = head ( positions xs x ++ [0] )

Lazy evaluation only generates head element!

First Occurrence (3)

Lazy evaluation allows upper bound to be removed

    positions :: Eq a => [a] -> a -> [Int]
    positions xs x = [ i | (i,y)<-zip [1..] xs, x == y]

Key Ideas

Source Code

The Haskell module for this chapter is in MoreLists.hs.