Exploring Languages
with Interpreters
and Functional Programming

Chapter 13
List Programming

H. Conrad Cunningham (after class)

24 September 2018

Copyright (C) 2017, 2018, H. Conrad Cunningham

Acknowledgements: I originally created these slides in Fall 2017 to accompany what is now Chapter 13, List Programming, 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 September 2018 is a recent version of Firefox from Mozilla.

List Programming

Lecture Goals

Haskell Data Types

Immutable:

not subject to change as program executes

Lists

List Syntactic Sugar

Syntactic sugar:

notation that simplifies expression, but adds no new functionality

List Operations

String

Evaluation (1)

len "five"
\Longrightarrow if "five" == [] then 0 else 1 + len (tail "five")
\Longrightarrow if False then 0 else 1 + len (tail "five")
\Longrightarrow 1 + len (tail "five")
\Longrightarrow 1 + len "ive"

Evaluation (2)

\Longrightarrow 1 + (if "ive" == [] then 0 else 1 + len (tail "ive"))
\Longrightarrow 1 + (if False then 0 else 1 + len (tail "ive"))
\Longrightarrow 1 + (1 + len (tail "ive"))
\Longrightarrow 1 + (1 + len "ve")

Evaluation (4)

\Longrightarrow 1 + (1 + (if "ve" == [] then 0 else 1 + len (tail "ve")))
\Longrightarrow 1 + (1 + (if False then 0 else 1 + len (tail "ve")))
\Longrightarrow 1 + (1 + (1 + len (tail "ve")))
\Longrightarrow 1 + (1 + (1 + len "e"))

Evaluation (5)

\Longrightarrow 1 + (1 + (1 + (if "e" == [] then 0 else 1 + len (tail "e"))))
\Longrightarrow 1 + (1 + (1 + (if False then 0 else 1 + len (tail "e"))))
\Longrightarrow 1 + (1 + (1 + (1 + len (tail "e"))))
\Longrightarrow 1 + (1 + (1 + (1 + len "")))

Evaluation (6)

\Longrightarrow 1 + (1 + (1 + (1 + (if "" == [] then 0 else 1 + len (tail "")))))
\Longrightarrow 1 + (1 + (1 + (1 + (if True then 0 else 1 + len (tail "")))))
\Longrightarrow 1 + (1 + (1 + (1 + 0)))
\Longrightarrow 1 + (1 + (1 + 1))
\Longrightarrow 1 + (1 + 2)
\Longrightarrow 1 + 3
\Longrightarrow 4

Evaluation (7)

Polymorphic Lists

Polymorphism:

property of having “many shapes”

Kinds of Polymorphism (1)

From Chapter 5 (section 5.2.5)

  1. Ad hoc polymorphism, same function name denotes different implementations depending on use

    1. Overloading, compiler determines which to invoke, early binding

      E.g. + in Java, Haskell type classes

    2. Subtyping, runtime searches hierarchy of types, late binding

      Called just polymorphism in Java, does not exist in Haskell

Kinds of Polymorphism (2)

  1. Parametric polymorphism, same implementation used for different types

    Called generics in Java, Haskell just polymorphism

Programming with List Patterns

Add List of Int (1)

Add List of Int (2)

    sum' :: [Int] -> Int  -- sum in Prelude 
    sum' []     = 0           -- nil list 
    sum' (x:xs) = x + sum' xs -- non-nil list 

Add List of Int (3)

Exercise: Write variant of sum' that uses a tail recursive auxiliary function.

Multiply List of Integer (1)

    product' :: [Integer] -> Integer  -- product in Prelude
    product' []     = 1               -- nil list
    product' (0:_)  = 0               -- 0 at head
    product' (x:xs) = x * product' xs -- non-nil, non-zero

Multiply List of Integer (2)

    product' :: [Integer] -> Integer  -- product in Prelude
    product' []     = 1               -- nil list
    product' (0:_)  = 0               -- 0 head, don't care
    product' (x:xs) = x * product' xs -- non-nil, non-zero

Comparison of sum' and product'

Length of List

    length' :: [a] -> Int  -- length in Prelude
    length' []     = 0              -- nil list
    length' (_:xs) = 1 + length' xs -- non-nil list

Adjacent Duplicates (1)

Adjacent Duplicates (2)

Adjacent Duplicates (3)

How can we make work for polymorphic list?

More List Patterns (1)

Pattern Argument Succeeds? Bindings
1 1 yes none
x 1 yes x \leftarrow 1
(x:y) [1,2] yes x \leftarrow 1, y \leftarrow [2]
(x:y) [[1,2]] yes x \leftarrow [1,2], y \leftarrow []
(x:y) ["olemiss"] yes x \leftarrow "olemiss", y \leftarrow []
(x:y) "olemiss" yes x \leftarrow ’o’, y \leftarrow "lemiss"

More List Patterns (2)

Pattern Argument Succeeds? Bindings
(1:x) [1,2] yes x \leftarrow [2]
(1:x) [2,2] no none
(x:_:_:y) [1,2,3,4,5,6] yes x \leftarrow 1, y \leftarrow [4,5,6]
[] [] yes none
[x] ["Cy"] yes x \leftarrow "Cy"
[1,x] [1,2] yes x \leftarrow 2

More List Patterns (3)

Pattern Argument Succeeds? Bindings
[x,y] [1] no none
(x,y) (1,2) yes x \leftarrow 1, y \leftarrow 2

Data Sharing

    xs = [1,2,3]
    ys = 0:xs 
    zs = tail xs 

Drop Elements from List (1)

Drop Elements from List (2)

        drop' :: Int -> [a] -> [a]  -- drop in Prelude
        drop' n xs | n <= 0 = xs 
        drop' _ []          = []
        drop' n (_:xs)      = drop' (n-1) xs 

Take Elements from List (1)

Take Elements from List (2)

~~~{.haskell}
    take' :: Int -> [a] -> [a] -- take in Prelude
    take' n _ | n <= 0 = []
    take' _ []         = []
    take' n (x:xs)     = x : take' (n-1) xs
~~~

Key Ideas

Code

The Haskell code for this section is in file ListProg.hs.