0% found this document useful (0 votes)
4 views65 pages

05 Intro2FunctionalPP

The document provides an introduction to the Functional Programming Paradigm using Haskell, covering its principles, advantages, and basic rules. It discusses key features of functional languages, the significance of Haskell, and various data structures such as lists. Additionally, it includes examples of Haskell programs and their syntax, emphasizing the importance of program layout and local definitions.

Uploaded by

Lucky John
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views65 pages

05 Intro2FunctionalPP

The document provides an introduction to the Functional Programming Paradigm using Haskell, covering its principles, advantages, and basic rules. It discusses key features of functional languages, the significance of Haskell, and various data structures such as lists. Additionally, it includes examples of Haskell programs and their syntax, emphasizing the importance of program layout and local definitions.

Uploaded by

Lucky John
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 65

The Functional Programming Paradigm

An Introduction through Haskell

Sahalu Junaidu
ICS Department
KFUPM

1
Introduction to the Functional Paradigm (FP)

• Part 1: The FP and Haskell


• Part 2: Basic Haskell Rules
• Part 3: Data Structures in Haskell
• Part 4: Higher Order Functions in Haskell
• Part 5: Algebraic Data Types in Haskell

2
Part 1

The Functional Paradigm and Haskell

3
The Functional Paradigm and Haskell
• The Functional Paradigm
– What is Functional Programming?
– Why Functional Programming?

• Introduction to Haskell

• Basic Types

• Names in Haskell

• Simple Haskell Programs

4
What is the Functional Paradigm ?

• Program viewed as a collection of functions.


– Functional programming is a style of programming in which the
basic method of computation is the application of functions to
arguments;
– A functional language is one that supports and encourages the
functional style.
• Functional languages try to model mathematical functions
as much as possible.
• There are no assignments; assignments are considered bad
and therefore banned!
• Emphasize on simple and clean semantics.
• Example languages: Scheme, MirandaTM, Haskell, ML

5
The Functional Paradigm: Computational Foundation
• Unlike imperative languages, functional languages (FLs)
are not based on the von Neumann computer
• FLs are based on a computation model called lambda
calculus
• The lambda calculus is a simple mathematical theory
developed before the advent of digital computers
• The lambda calculus was intended to be a foundation of
mathematics in the 1930s
• The lambda calculus has very few syntactic constructs but it
is Turing complete
– It can compute any function that can be computed by a computing
device
• FLs are often considered as sugared versions of the lambda
calculus

6
Functional Languages: Key Features

• High-level of abstraction
– Functional languages are among the highest-level languages in
present-day use
• Clean and simple semantics
– Easier to reason about functional programs than imperative
programs
• Conciseness (expressivity)
– Support for rapid application development
• Support for concurrency
• High orthogonality
– Few language constructs compared to imperative or OO languages
• Lazy evaluation (for some of them)
7
Why Functional Languages?

The main reason we use functional programming is to


reduce the time it takes to bring a product to the market and
to reduce the total effort required to design and maintain
our products. As functional programs are both shorter and
more succinct than corresponding programs in languages
such as C, C++, or Java, the number of errors made in the
design is also greatly reduced

– Ericsson Telecom

• Widely used for teaching introductory computer science


courses in European universities, especially
8
Costs of Functional Languages (FLs)
• Generally, FLs do not run as fast as imperative languages on today’s
von Neumann computers

• Non-trivial I/O and state-bound algorithms are relatively more difficult


to express

• Non-determinism (required in schedulers and similar systems


programs) is relatively more difficult to express in FLs

• Lazy evaluation hinders efficient implementation in terms of memory


usage

• Debugging lazy functional programs is generally more difficult due to


their demand-driven evaluation mechanism

9
Introduction to Haskell
• Haskell is named after the logician Haskell B. Curry (1900-1982)
who re-invented and developed combinatory logic
• It is a lazy purely functional language largely derived from
MirandaTM but with several extensions.
• Haskell was designed by a committee from the functional
programming community in April 1990.
• Main features of Haskell are:
– strong, static, polymorphic typing
– Higher-order functions
– user-defined algebraic data types
– pattern-matching list comprehensions
– systematic operator overloading
– lazy evaluation
– etc.

10
Haskell Types
Type Description Examples Operators
Int Fixed-precision integers 3,7,-12 +,-,*,==,>, etc
Integer Arbitrary-precision 3,7,- +,-,*,==,>, etc
integers 12,243290200817664
0000
Float 3,3.0,7.2,pi +,-,*,==,>, etc
Double 3,3.0,7.2,pi +,-,*,==,>, etc

Char Single of characters ‘a’,’Z’,’3’ ==,<,etc

String Strings of characters “ICS”,”13.11” ==,<,++,etc


Bool Boolean (logical) values True, False ==,&&,||,not,etc
List types Values of the same type [1,2], [[‘m’],[‘3’]]
Tuple types Values of different type (1,’m’),(“3”,True,’3’)

Function types A mapping from values of not :: Bool  Bool


one type to values of isDigit ::Char  Bool
another type

11
Names in Haskell

• There are six kinds of names in Haskell


– those for variables and constructors denote values;
– those for type variables, type constructors, and type classes refer to
entities related to the type system; and
– module names refer to modules.
• Some restrictions on naming:
– names for variables and type variables are identifiers beginning
with lowercase letters or underscore;
– the other four kinds of names (constructors, type constructors, type
classes and module names) are identifiers beginning with
uppercase letters.

12
Reserved Names (keywords) in Haskell

• The following are special words in Haskell (See Appendix


B.2 in the Haskell Report):

case , class , data , default , deriving , do , else ,


if , import , in , infix , infixl , infixr , instance ,
let , module , newtype , of , then , type , where ,
_ , as , qualified , hiding

13
Haskell Programs
• A Haskell program is a collection of modules, one of which,
by convention, must be called Main and must export the
value main.
– This applies to compiled implementations and is of less significance
in interpreted implementations like Hugs (that we’ll be using)
• A module defines a collection of values, datatypes, type
synonyms, classes, etc.
• The value of the program is the value of the identifier main
in module Main
• Modules may reference other modules via explicit import
declarations
• Modules may be mutually recursive.
• Modules are used solely for name-space control
– multi-module Haskell program can be converted into a single-
module program by giving each entity a unique name
14
Example 1: A Welcome Program
module Main where

main = print welcome

welcome = "Salaam Shabab"

15
Example 2: Simple Int Functions
module L01_Example02 where
main = print (factorial p)
p:: Int -- type signature
p=7
q = -9
factorial:: Int -> Int
factorial 0 = 1
factorial n = n*factorial(n-1)
fact 0 = 1
fact n | n > 0 = n*fact(n-1) -- guard
| otherwise = error “fact: invalid argument”

fibonacci 0 = 0
fibonacci 1 = 1
fibonacci n | n > 0 = fibonacci (n-1) + fibonacci (n-2)
| otherwise = error “Fibonacci: -ve argument”

16
Example 3: Simple Bool Functions
module L01_Example03 where

main = print (exclusiveOR True False)

isZero 0 = True -- try replacing the first character of a method to upper case
isZero _ = False -- to see sample error messages

exclusiveOR x y = if x==y then False else True

exclusiveOR2 True x = not x


exclusiveOR2 False x = x

--exclusiveOR2 x y = (x || y) && not (x && y)


-- the following function checks equivalence of exclusiveOR and exclusiveOR2
alwaysTrue a b = exclusiveOR a b == exclusiveOR2 a b

allTrue = [alwaysTrue True False, alwaysTrue True True, alwaysTrue


False True, alwaysTrue False False]
17
Part 2

Basic Haskell Rules

18
Basic Haskell Rules
• Program Layout

• Associativity in Haskell

• Local Definitions

• Scope

19
Program Layout Rules
• We have seen that a Haskell program contains a series of
definitions, one after another
• Haskell uses the layout of the program to ‘know’ where one
definition ends and where the next definition begins
• Formally, a definition is ended by the first piece of text
which
– lies at the same level (start in the same column) or
– lies to the left of the start of the definition
• This layout rule is called offside rule because it reminds of
the idea of being ‘offside’ in soccer
• It is therefore sensible in writing a sequence of definitions to
give all of them the same level of indentation
• An alternative way is to use explicit braces and commas to
specify definitions belonging together or in the same group20
Example 1: Layout Rules
module L02_Example01 where

main = print (quadruple 5)

square n =
n*n -- bad layout: since this is part of the definition for square,
-- it must be indented to the right of s in square

-- there is no error in the following:

quadruple k =
square
(
square
k
)

21
Example 2: Layout Rules
module L02_Example02 where

{main = print (sumFromTo m n);

-- more than one definition on a line using ';' separator

m = 2; n = 7;sumFromTo x 0 = 0; sumFromTo x n =
if n < x then 0 else x + sumFromTo (x+1) n;}

22
Operators and Associativity
• Haskell contains various operators and also allows programmers to define
their own operators
• Haskell predefined operators with their precedences and associativities
are (we will not cover all of these operators):

23
Operators and Functions
• Operators can be converted to functions, which precede their arguments
using the following rule:
– any two-parameter operator can be used in a prefix expression by enclosing it
in parenthesis
– Example: x + y is identical to (+) x y

• Functions can also be used in infix form using the rule:


– the name of any two-parameter function can be used in an infix form
expression by enclosing it in back-quotes (not forward quotes)
– Example: given f of two parameters, then f x y is identical to x `f` y

• The following example shows how you can define your own operator

24
Example 3: User-Defined Operators
module L02_Example03 where

main = print (maxOf3 a b c); --anotherMax a b c

infixl &&& -- left associative,precedence defaults to 9

x &&& y = if x>y then x else y

a = 2;b = -7;c = 3

maxOf3 p q r = if (&&&) p q < r then r else (&&&) p q


-- if p &&& q < r then r else p &&& q -- alternative

anotherMax a b c = a &&& b &&& c

-- what is the type of anotherMax?

25
Local Definitions
• The definitions we have seen so far are all top-level
definitions
• Haskell allows making definitions local to a top-level
equation or definition
• Local definitions for a function are introduced using the
where keyword
• Local definitions can also be made for an expression
• Local definitions for an expression are introduced using the
let keyword:
let
x = 3+2
in x^2 + 2*x - 4
• Both functions and values can be defined locally
• The offside rule must be followed in local definitions
26
Example 4: Local Definitions
module L02_Example04 where

main = print (maxThreeOccurs a b c);


infixl &&&
x &&& y = if x>y then x else y
a = 3;b = -7;c = 3
--finds max of the three with its frequency
maxThreeOccurs p q r = (max, freq)
where
max = anotherMax p q r -- these two lines must
freq = freqOfMax max p q r -- be vertically aligned
freqOfMax m a b c =
let
– local function to an expression
isVal x = if x == m then 1 else 0
in isVal a + isVal b + isVal c

anotherMax a b c = a &&& b &&& c


27
Scope of Names
• The scope of a definition is that part of the program in which the
definition can be used

• The scope of a top-level definition is the entire script in which they are
defined
– In particular, a definition, f, can be used in definitions which occur before f in
the script (cf. with Java and C)

• Local definitions are intended to be ‘visible’ only in the equation in


which they appear

• The scope of function parameter names is the right-hand side of the


equation in which they occur

28
Example 5: Scope of Names
module L02_Example05 where

main = print (maxThreeOccurs a b c);


infixl &&&
x &&& y = if x>y then x else y
a = 3;b = -7;c = 3
--finds max of the three with its frequency
maxThreeOccurs p q r = (max, freq)
where
max = anotherMax p q r -- these two lines must
freq = freqOfMax max p q r -- be vertically aligned
freqOfMax m a b c = --replace with (freqOfMax m x y z) and observe
let
isVal a = if a == m then 1 else 0 --three a's in scope, here!
in isVal a + isVal b + isVal c --two a's, b's and c's in scope!

anotherMax a b c = a &&& b &&& c

29
Part 3

Data Structures in Haskell

30
Data Structures in Haskell
• Lists: the ubiquitous data structure

• Defining Functions over Lists


– Pattern Matching

• List Comprehension

• Lazy Evaluation
– Infinite Data Structures
31
Haskell Data Structures: Lists
• The most common data structure in functional languages is the List
• Lists are used to model a collection of objects in a program like:
– A telephone directory – a collection of name-number associations
– A book – a collection of chapters
– etc
• A list is an ordered sequence of items, all of the same type
• For any type t, there is a type of lists of items of type t, and this type is
written [t]:
– [1, 2, 3] :: [Int]
– [True, False] :: [Bool]
– [(4, ’a’), (-3, ’v’)] :: [(Int, Char)]
– [[7], [], 4 : []] :: [[Int]]
– [sum, length] :: [[Int] -> Int]
• String is a type synonym for [Char] and has special syntax
– [’i’, ’c’, ’s’] :: [Char] -- this line is the same as
– “ics" :: String -- this line
32
Building Lists in Haskell: Another Way

• Lists can also be built in Haskell using arithmetic sequences


as follows:
– [1, 2 .. 5] = [1, 2, 3, 4, 5]
– [1, 3 .. 8] = [1, 3, 5, 7]
– [8 .. 0] = [8, 9 .. 0] = []
– [1 ..] = [1, 2, 3, 4, 5, ...
– [False ..] = [False, True]
– [’a’ .. ’z’] = "abcdefghijklmnopqrstuvwxyz“
• The operator ‘:’ (called ‘cons’) is the constructor used to
build lists of items
• ‘:’ is right-associative and it is polymorphic:
(:) :: t -> [t] -> [t]

33
Defining Functions Over Lists
• Functions over lists are often recursive and defined by cases:
– A function defined over lists must work on empty and non-empty
lists

• Illustration: find the sum of list elements:


sum [] =0
sum (x:xs) = x + sum xs

• The above definition is based on pattern matching case


analysis:
– the pattern [] matches an empty list;
– the pattern (x:xs) matches any non-empty list
– The value x is the head of the list and xs is the tail of the list

• Exercise: Write a function, listLength, to calculate the


length of a given list 34
Example 1: List Processing Functions
module L03_Example01 where

main = print (insertionSort list)

insertionSort [] = []
insertionSort (x:xs) = insert x (insertionSort xs)

insert x [] = [x]
insert x (y:ys) = if x<=y then x:(y:ys) else y : insert x ys

list = [1.. 10] ++ [-10.. 0] ++ [7,5.. -6]

35
Example 2: Selection Sort
module L03_Example02 where

min2 a b = if a>= b then b else a

findMin [] = error "finMin of []"


findMin [x] = x
findMin (h:t) = min2 h (findMin t)

removeMin m [] = []
removeMin e (e1:t) = if e==e1 then removeMin e t else
e1:removeMin e t

selectionSort [] = []
selectionSort xs = first : selectionSort rest
where
first = findMin xs
rest = removeMin first xs

36
List Comprehension
• A list can be defined relative to another list (cf. mathematical set notation):

– [x * 2 | x <- [1, 2, 3, 4]] = [2, 4, 6, 8]


– [-x | x <- [6 .. 8]] = [-6, -7, -8]

• Conditions can be attached to the elements selected from the generator:

– [x * 3 | x <- [1 .. 4], even x] = [6, 12]

• More than one list can be used as a generator. Later lists vary faster in the result:
– [(x, y) | x <- [1 .. 3], y <- "abc"]
= [(1, ’a’), (1, ’b’), (1, ’c’), (2, ’a’), (2, ’b’),
(2, ’c’), (3, ’a’), (3, ’b’), (3, ’c’)]

• A pattern can be used instead of just a variable to select elements:


– [x + 3 | (True, x) <- [(False, 4), (True, 7), (False, 0)]]
= [10]
37
Example 3: List Comprehension
module L03_Example03 where

import Char(isDigit) -- note synxtax of import statement

main = print result

result = getDigits "ICS 313 Term 052"

getDigits [] = []
getDigits (c:rest) | isDigit c = c:getDigits rest
| otherwise = getDigits rest

getDigits2 str = [ c | c <- str, isDigit c]

squares = [ m*m | m <- [1..10], even m]

38
Example 4: List Comprehension
module L03_Example03 where
import L03_Example02
import Char(digitToInt) -- note: no implicit import
main = print (string2Int result);

string2Int :: String -> Int


string2Int [] = 0
string2Int (h:t) = hv*k + string2Int t
where
len = length t
k = 10^len
hv = digitToInt h

39
Example 5: Quick Sort
module L03_Example05 where

quicksort [] = []
quicksort (h:t) =
quicksort [ x | x <- t, x < h] ++
[h] ++
quicksort [ x | x <- t, x > h]

quicksort2 order [] = []
quicksort2 order (h:t) =
quicksort2 [ x | x <- t, order x h ] ++
[h] ++
quicksort2 [ x | x <- t, order h x ]

order a b = a > b

40
Lazy Evaluation
• Lazy evaluation is a term describing how language expressions are evaluated

• Lazy evaluation is also called normal-order reduction, delayed evaluation, and


call-by-need

• The principle is to delay the evaluation of any expression until it is absolutely


necessary
– Enables the definition of infinite data structures

• Languages that use normal-order reduction are called lazy (e.g., Haskell,
Miranda, Hope)

• Languages that eagerly evaluate expressions are called strict (e.g., Scheme, Java,
C)

• Example
– fst (10, 10/0)
41
Example 06: Infinite List of Prime Numbers

module L03_Example07 where

main = print (take 10 primes)

primes = sieve [2..]

sieve (h:t) = h : sieve [ n | n <- t, mod n h /= 0]

42
Part 4

Higher-Order Functions

43
Higher-Order Functions in Haskell

• Functions as Arguments

• Functions as Values

• Folding List Elements

• Filtering List Elements

44
Functions as Arguments
• As mentioned earlier functions in Haskell are first-class citizens
– They can be passed as arguments to functions, returned by functions as results
and stored as elements in data structures
• A function can take another function as argument as follows:

myMap:: (Int -> Int) -> [Int] -> [Int]


myMap f [] = []
myMap f (h:t) = f h:myMap f t

• From this definition, any one-parameter function that takes an Int and
returns an Int can be passed as parameter to myMap
• In fact, there is nothing specific to the Int type in the defintion of
myMap; removing the type signature, Haskell will infer the polymorphic
type
myMap :: (a -> b) -> [a] -> [b]
• This type now means that any one-parameter function can be passed as a
parameter to myMap
45
Example 01: Functions as Arguments

module L04_Example01 where

main = print doubles

myMap f [] = []
myMap f (h:t) = f h:myMap f t

twice x = 2*x

doubles = myMap twice [1..10]


lengths = myMap length ["Muhammad”,"Ali", "Ahmad",
"Isa"]
booleans = myMap even [3..19]
myWords = myMap words ["This is quite amazing Shabab!"]
46
Example 02: Functions as Values

module L04_Example02 where


import L04_Example01 (myMap)

scaleBy x y = x*y + y

myValues = myMap (scaleBy 0.5)[1..10]

{- applying scaleBy to one parameter returns a function


which in turn requires one parameter to produce x*y+y
-}
myFunctions = myMap scaleBy [1..10]

scaled x = [f x | f <- myFunctions]

47
Folding List Elements
• We have defined a findMin function, using an auxiliary function min2, in our
selection sort example
• To sort elements in reverse order requires changing min2 or defining a max2
function in addition to a findMax function
• The definition of max2 will be very similar to that of min2 and the definition of
findMax will also be almost identical to finMin
• We can use higher-order functions to combine the definitions of min2 and
max2 as follows:

min2OrMax2 op x y = x `op` y

• Similarly, can combine the definitions of findMin and findMax as follows:

findMinOrMax f [] = error “findMinOrMax of []”


findMinOrMax f [x] = x
findMinOrMax f (h:t) = f h (findMinOrMax f t)

• Again, you will notice that findMinOrMax will be polymorphic;


min2OrMax2 is only one instance of a two-parameter function that it can take
as argument 48
Example 03: Folding List Values
module L04_Example03 where

min2OrMax2 op x y = if (x `op` y) then x else y

findMinOrMax f [] = error "findMinOrMax of []"


findMinOrMax f [x] = x
findMinOrMax f (h:t) = f h (findMinOrMax f t)
{- compare findMinOrMax with functions foldl and foldr
provided inside the Haskell Prelude
-}
findMin, findMax:: Ord a => [a] -> a
-- findMin and findMax are function values
findMin = findMinOrMax (min2OrMax2 (<=))
findMax = findMinOrMax (min2OrMax2 (>=))
sumAll = findMinOrMax (+) [1..10]
factorial n = findMinOrMax (*) [1..n]
49
Example 04: Filtering List Values
module L04_Example04 where
import Char (isDigit, isAlpha)

filterString p [] = []
filterString p (h:t) | p h = h:filterString p t
| otherwise = filterString p t

filterString2 p s = [c | c <- s, p c]

{- compare findString with the function filter


provided inside the Haskell Prelude
-}

digits str = filterString isDigit str


letters str = filterString isAlpha str

50
Example 05: Modeling Iteration

module L04_Example05 where

iteration 0 f x = x
iteration n f x
| n > 0 = iteration (n-1) f (f x)
| otherwise = recip (iteration (k-1) f (f x))
where k = -n

twice x = 2*x

val = iteration 5 twice 1 --what is the output?

Exercise: Use this to define ab for integers a and b.


51
Part 5

Algebraic Data Types

52
Algebraic Data Types in Haskell

• Enumerated Types

• Product Types

– Type Synonyms

• Union Types

• Polymorphic Algebraic Types

53
Algebraic Data Types in Haskell
• Our programs so far contain the base data types, tuple types
and list types
• There are other objects that are difficult to model using the
type constructs we have seen so far:
– Type of months: January, …, December
– Objects whose elements are either a number or a string: a house in a
street will either have a number or a name, for instance
– Tree or graph objects
• Haskell has facilities that enable users to define their own
types as an aid to modeling power
• We will consider type definitions using the following
keywords
– data – used to introduce algebraic data types
– type – use to introduce type synonyms (cf. typedef in C)
54
Enumerated Types
• The simplest algebraic type definitions are just an enumeration of the
elements or values of that new type.
• For example, the days of the week could be defined as follows:

data Day = Sun | Mon | Tue | Wed | Thu | Fri | Sat

• The new type name is Day and it has seven members: Sun, Mon, ...,
Sat.
• The values Sun, Mon, Tue, …, Sat are called the constructors of the
type Day
• Functions over this type are defined using pattern matching:

isWeekDay :: Day -> Bool


isWeekDay Thu = False
isWeekDay Fri = False
isWeekDay _ = True
55
Displaying New Types
• To display objects of a user-defined class properly in Java, the
programmer must override the toString() method

• Haskell makes life easier for programmers because it can be made to


generate definitions over a new type automatically

• That is, definitions for ==, ordering (<, >, etc), enumeration and
display functions can be generated automatically for a new type

• This can be done using the deriving clause:

data Day = Sun | Mon | Tue | Wed | Thu | Fri | Sat deriving Eq

• In most cases the automatic definitions are satisfactory but sometimes


you need to change the default definition
56
Example 1: Enumerated Types
module L05_Example01 where

data Day = Sun | Mon | Tue | Wed |


Thu | Fri | Sat
deriving (Eq, -- generate ==, /= etc
Ord, -- generate <, >, etc
Show, -- generate show, etc
Enum -- generate .., etc
)

isWeekDay :: Day -> Bool


isWeekDay Thu = False
isWeekDay Fri = False
isWeekDay _ = True

57
Product Types
• Instead of using a tuple, we can define a type with a number of components, often
called a product type, as an algebraic type
• Example:

data Student = Person Id Name GPA


type Id = Int -- type synonym definition
type Name = String -- another synonym definition
type GPA = Float -- yet another synonym definition

• To construct an element of type Student, you need to supply three objects , say
iD of type Id, name of type Name and gpa of type GPA.
– The element formed from them will be Person iD name gpa
• Constructors introduced using algebraic types are like functions
– except that they compute nothing; they merely package their arguments
– Person id name gpa is a result of applying the function Person to the three
arguments
– Person:: Id -> Name -> GPA
• A tuple can be used as an alternative way of defining the Student type above as:
type Student = (Id, Name, GPA)
58
Example 2: Product Types
module L05_Example02 where

data Student = Person Id Name GPA deriving Show

type Id = Int
type Name = String
type GPA = Float

toString:: Student -> String


toString (Person sId name gpa) =
show sId ++ s ++ name ++ s ++ show gpa
where s = " "

59
Algebraic Types vs Tuples (Synonyms)
• Advantages of algebraic types
– Constructor makes code clearer; the type carries an
explicit label or tag
– Constructor prevents mistaking some other Int, String,
Float combination for a Student
– Error messages preserve algebraic type names, but may
lose synonym names
• Advantages of tuples
– Tuples are more compact (no constructor) leading to
shorter definitions
– Using tuples allows use of polymorphic functions such as
fst and zip
– No type definition is needed
60
Union Types
• Consider the task of modeling various geometrical shapes
• Using an enumerated type we can distinguish between different kinds of shapes,
but we cannot carry other information such as dimensions
• The alternatives in a data definition can include other types, rather than being
simple constants like Mon and Tue

data Shape = Circle Float |


Rectangle Float Float deriving (Eq, Ord, Show)

• Here, Circle and Rectangle are constructors functions:

Circle :: Float -> Shape


Rectangle:: Float -> Float -> Shape

• In other words, Circle constructs a Shape from any Float value


• Constructor functions are the only functions that can appear in patterns.

61
Example 3: Union Types
module L05_Example03 where

data Shape = Circle Float |


Rectangle Float Float deriving (Eq, Ord, Show)

-- what is the type of isRound?


isRound (Circle r) = True
isRound (Rectangle l b) = False

-- what is the type of area?


area (Circle r) = pi * r^2
area (Rectangle l b) = l * b

getWidth (Rectangle l w) = w

62
Example 4: Polymorphic Types I
module L05_Example04 where
bst = mkBSTree [10,8,20,7,9,19,23]
data BSTree a = Nil | Node a (BSTree a) (BSTree a) deriving Show
add:: (Ord a) => a -> BSTree a -> BSTree a
add x Nil = Node x Nil Nil
add x (Node a left right) =
if x==a then error "Element exists!"
else if x<a then (Node a (add x left) right)
else (Node a left (add x right))

mkBSTree::(Ord a) => [a] -> BSTree a


mkBSTree = mkBSTree Nil
where mkBSTree t [] = t
mkBSTree t (x:xs) = mkBSTree (add x t) xs

postOrder:: BSTree a -> [a]


postOrder Nil = []
postOrder (Node a l r) = postOrder l ++ postOrder r++[a]
63
Example 5: Polymorphic Types II
module L05_Example05 where
main = print graph
vals :: [[Int]]
vals = [[2,3,5],[4,3],[5,6],[6],[6,8],[7],[],[7]]
graph = buildGraph vals
data Vertex = Vertex Int deriving (Eq, Ord, Show)
data Edge = Edge Int Int deriving (Eq, Ord, Show)
data Graph = Graph [Vertex] [Edge] deriving (Eq, Ord, Show)
buildGraph:: [[Int]] -> Graph
buildGraph xss = Graph vs es
where
es = graphBuilder 1 xss
vs = [Vertex v | v<- [1..(length xss)]]
graphBuilder n [] = []
graphBuilder n (h:t) = [Edge n x | x <- h] ++ graphBuilder (n+1) t
isComplete :: Graph -> Bool
isComplete (Graph vs es) = foldr (&&) True result
where
result = [elem (Edge x y) es | Vertex x <-vs, Vertex y <- vs, x/= y]

64
References

1. Haskell: The Craft of Functional Programming, By Simon


Thompson, Addison-Wesley, 1996, ISBN 0-201-40357-9
2. Haskell 98 Language and Libraries, The Revised Report, SL Peyton
Jones (editor), http://www.haskell.org/definition/

65

You might also like