05 Intro2FunctionalPP
05 Intro2FunctionalPP
Sahalu Junaidu
ICS Department
KFUPM
1
Introduction to the Functional Paradigm (FP)
2
Part 1
3
The Functional Paradigm and Haskell
• The Functional Paradigm
– What is Functional Programming?
– Why Functional Programming?
• Introduction to Haskell
• Basic Types
• Names in Haskell
4
What is the Functional Paradigm ?
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?
– Ericsson Telecom
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
11
Names in Haskell
12
Reserved Names (keywords) in Haskell
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
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
isZero 0 = True -- try replacing the first character of a method to upper case
isZero _ = False -- to see sample error messages
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
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
quadruple k =
square
(
square
k
)
21
Example 2: Layout Rules
module L02_Example02 where
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
• The following example shows how you can define your own operator
24
Example 3: User-Defined Operators
module L02_Example03 where
a = 2;b = -7;c = 3
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
• 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)
28
Example 5: Scope of Names
module L02_Example05 where
29
Part 3
30
Data Structures in Haskell
• Lists: the ubiquitous data structure
• 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
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
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
35
Example 2: Selection Sort
module L03_Example02 where
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):
• 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’)]
getDigits [] = []
getDigits (c:rest) | isDigit c = c:getDigits rest
| otherwise = getDigits rest
38
Example 4: List Comprehension
module L03_Example03 where
import L03_Example02
import Char(digitToInt) -- note: no implicit import
main = print (string2Int result);
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
• 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
42
Part 4
Higher-Order Functions
43
Higher-Order Functions in Haskell
• Functions as Arguments
• Functions as Values
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:
• 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
myMap f [] = []
myMap f (h:t) = f h:myMap f t
twice x = 2*x
scaleBy x y = x*y + y
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
filterString p [] = []
filterString p (h:t) | p h = h:filterString p t
| otherwise = filterString p t
filterString2 p s = [c | c <- s, p c]
50
Example 05: Modeling Iteration
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
52
Algebraic Data Types in Haskell
• Enumerated Types
• Product Types
– Type Synonyms
• Union 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:
• 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:
• That is, definitions for ==, ordering (<, >, etc), enumeration and
display functions can be generated automatically for a new type
data Day = Sun | Mon | Tue | Wed | Thu | Fri | Sat deriving Eq
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:
• 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
type Id = Int
type Name = String
type GPA = Float
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
61
Example 3: Union Types
module L05_Example03 where
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))
64
References
65