View
217
Download
1
Embed Size (px)
Citation preview
BB1756: Software Development
Functional Programming in Haskell
2010/2011
Dan Russell
Email: [email protected]: http://staffnet.kingston.ac.uk/~ku02309
BB1756: SWD 2
Administration
Materials for the course, including handouts,
the module guide, and the lab session worksheets, will be on my SWD web page at:
http://staffnet.king.ac.uk/~ku02309/courses/swd1011.html
This page can be accessed directly from StudySpace.
Exercise Classes: using the Hugs interpreter.
BB1756: SWD 3
Software Development
A.K.A. The Development of Software
A.K.A. The analysis of a problem and the
design (using a choice of media) and implementation (using a programming
language) of a solution to the problem.
BB1756: SWD 4
Programming Paradigms
Various including:
Imperative/Procedural, Object-Oriented and Functional
Each paradigm is populated with a collection of
programming languages and support tools such
as analysis and design methodologies (ADMs).
BB1756: SWD 5
Programming Languages
Imperative/Procedural: Fortran, Cobol, Pascal, Basic and C
Object-Oriented: C++, Java and C#
(plus JavaScript which is a Web
scripting language that you will use
at Level 5)
Functional: Miranda, Scheme, ML and Haskell
BB1756: SWD 6
Functional Programming
Programming with functions
in contrast to
Programming with objects
and also in contrast to
Programming with procedures
BB1756: SWD 7
Functional Programming
The programming language we use on this course
is Haskell 98.
See http://www.haskell.org/
There are various implementations of the language. The one we will use on this course is Hugs 98.
Runs on: Windows, Unix, Linux and MacOS.
See http://www.haskell.org/hugs/
BB1756: SWD 8
FORMALITY
Every programming language is a formal language which has to be adhered to for a program to work.
That is, it will have a set of rules regarding things like:
-- what is an acceptable name;
-- what is acceptable layout;
-- whether it is case-sensitive or not;
and so on…
BB1756: SWD 9
FORMALITY
Rule 1:
Every function name MUST begin with a lower case letter.
Rule 2:
No spaces are allowed in any name.
BB1756: SWD 10
Your First Problem
Define a function which doubles its input.
The analysis could include some sample input/output values to:
i. make sure that you understand the problem;ii. get an idea of the number and kind of input(s)
required;iii. get an idea of the kind of output required.
Note: These are non-programming issues. If you don’t understand the problem there is no way you can find a solution.
BB1756: SWD 11
Your First ProblemDefine a function which doubles its input.
Input Output
1
7
43
-9
A textual description of the function based on the above is often useful.
Multiply the input value by 2.
So how many input(s) are required, what are they, and what kind of output is required?
BB1756: SWD 12
Your First Problem
So when designing the solution we need a function which requires a single number input, and returns a number as output.
Part of the design process is deciding on a name for the function and a name for each input value.
The function name should suggest what the function does.
The input name should be short but should also give an indication of what the input is, if possible.
BB1756: SWD 13
Your First Problem
Which of the following combinations of function and input names is sensible?
Function Name Input Name
f x carrot k square t double double double n
d n
So now all we have to do is implement the solution!
BB1756: SWD 14
Your First Haskell Program
module Program1 where
-- This is a comment. A module hosts a collection
-- of definitions. A module name begins with an
-- upper case (CAPITAL) letter.
double n = 2 * n
-- Another comment. The function called
-- double returns double the input value.
-- The input value is called n.
BB1756: SWD 15
Your First Haskell Program
Lets use the program that we have just written.
Main> :l Program1
Reading file "Program1.hs":
Hugs session for:
C:\Program Files\Hugs98\lib\Prelude.hs
Program1.hs
Main> double 3
6
Main> double 27
54
Main> double 1312
2624
Main> double 43.2
86.4
This is how you load the program
This confirms that the program has been found and is OK.
Examples of using a function definedin the program.
Note: the function ALWAYS appears to the left of its argument(s).
BB1756: SWD 16
Your First Haskell Program
Lets try to use a program that we have not yet written.
Main> :l Program2
Reading file "Program2":
ERROR "Program2" - Unable to open file "Program2"
Main> :l Program1
Reading file "Program1.hs":
Hugs session for:
C:\Program Files\Hugs98\lib\Prelude.hs
Program1.hs
Main> duoble 7654ERROR - Undefined variable "duoble“
Main>
This indicates that the programdoes not exist.
Now Program1 has to be loaded again.
This error message is receivedwhen the function cannot be found.
BB1756: SWD 17
Your First Haskell Program
Lets continue to use the program.
Main> double
Main> double 'B'
ERROR - Illegal Haskell 98 class constraint in inferred type
*** Expression : double 'B'
*** Type : Num Char => Char
This indicates that the functionis being applied to the wrongtype of thing.
BB1756: SWD 18
FORMALITY
Rule 3:
When using a function it must always appear to the left of the thing(s) to which it is applied (the argument(s)).
Rule 4:
There must always be at least one space between a function and its argument(s).
BB1756: SWD 19
Your Second Problem
Define a function which returns the maximumof two integers.
The analysis could include some sample input/output values to:
i. make sure that you understand the problem;ii. get an idea of the number and kind of input(s)
required;iii. get an idea of the kind of output required.
Note: These are non-programming issues. If you don’t understand the problem there is no way you can find a solution.
BB1756: SWD 20
Your Second Problem
Define a function which returns the maximum oftwo integers.
Input 1 Input 2 Output 1 5 7 3 43 43 - 9 0
A textual description of the function based on the above is often useful.
If the first input is less than the second then the second is returned. If the first input is greater than or equal to the second then the first is returned.
BB1756: SWD 21
Your Second Problem
So when designing the solution we need a function which requires two integer (whole number) inputs, and returns an integer as output.
Part of the design process is deciding on a name for the function and a name for each input value.
The function name should suggest what the function does.
The input names should be short but should also give an indication of what the input is, if possible.
BB1756: SWD 22
Your Second Problem
Which of the following combinations of function and input names is sensible?
Function Name Input 1 Name Input 2 Name
f x y carrot k t double m n maxOf2 i i maxOf2 i j maximum x y
So now all we have to do is implement the solution!
BB1756: SWD 23
Your Second Haskell Program
module Program2 where
-- The function maxOf2 takes two integers-- and returns the maximum
maxOf2 i j = if i < j then j else i
-- Note how the definition mimics -- the description.
If the first input is less than the second then the second is returned. If the
first input is greater than or equal to the second then the first is returned.
BB1756: SWD 24
So What Does One Do?
Analyse: Investigate the problem, identifying the
essential features.
Design: Develop an implementable solution using
a chosen medium (i.e. text, pseudocode,
actual code or graphical)
Implement: Write code in your chosen programming
language that faithfully implements
the design.
BB1756: SWD 25
Essential Building Blocks of Functional Programming
#1
FUNCTIONSFUNCTIONS
A function is something which given a particular input
value(s) returns one particular output value.
We implement software in Haskell (Hugs) by defining
a collection of functions.
BB1756: SWD 26
Which of the following are functions?
1. daysInMonth
2. countryVisitedThisYear
3. capitalCityOf
4. sittingNextTo
BB1756: SWD 27
Some Functions...
-- addOne simply adds one to the input value
addOne n = n + 1
-- square uses the `to the power of’ operator ^
square m = m ^ 2
-- always7 ignores the input value and returns 7
always7 k = 7
-- isGreaterThan10 tests whether the input
-- number is greater than 10
isGreaterThan10 p = p > 10
BB1756: SWD 28
Essential Building Blocks of Functional Programming
#2
TYPESTYPES
A type is a collection of values (such as integers and
characters) which are grouped together because they are the same sort of thing.
They are used as part of the design process, and as
a guide to the user of a function as to what can be
input and what will be output.
BB1756: SWD 29
Some Functions (now with types)...
addOne n = n + 1
square m = m ^ 2
always7 k = 7
isGreaterThan10 p = p > 10
BB1756: SWD 30
Some Functions (now with types)...
Function Name Input Type Output Type
addOne :: Int -> Int
addOne n = n + 1
square m = m ^ 2
always7 k = 7
isGreaterThan10 p = p > 10
BB1756: SWD 31
Some Functions (now with types)...
Function Name Input Type Output Type
addOne :: Int -> Int
addOne n = n + 1
square :: Float -> Float
square m = m ^ 2
always7 k = 7
isGreaterThan10 p = p > 10
BB1756: SWD 32
Some Functions (now with types)...
Function Name Input Type Output Type
addOne :: Int -> Int
addOne n = n + 1
square :: Float -> Float
square m = m ^ 2
always7 :: any -> Int
always7 k = 7
isGreaterThan10 p = p > 10
BB1756: SWD 33
Some Functions (now with types)...
Function Name Input Type Output Type
addOne :: Int -> Int
addOne n = n + 1
square :: Float -> Float
square m = m ^ 2
always7 :: any -> Int
always7 k = 7
isGreaterThan10 :: Int -> Bool
isGreaterThan10 p = p > 10
BB1756: SWD 34
Why You Should Love Types! Why You Should Love Types!
The first reason why you should love types is that:
they provide a clear guide in development.
That is, after doing some analysis you can discover the required input type(s) and output type. Thus you know exactly what the functioncan be applied to and what it can return.
It is often the case that one specifies the type of a function well in advance of defining the function. This is so that other developersknow about the existence of the function and about how it may be used.
Note: Most popular programming languages are typed (have types). Thus these arguments apply for Java, C#, C++ and so on.
BB1756: SWD 35
Why You Should Love Types! Why You Should Love Types!
For example:
aFun :: Int -> Int aFun takes an Int and returns an Int
BB1756: SWD 36
Why You Should Love Types! Why You Should Love Types!
For example:
aFun :: Int -> Int
bFun :: String -> Bool
aFun takes an Int and returns an Int
bFun takes a String and returns a Bool
BB1756: SWD 37
Why You Should Love Types! Why You Should Love Types!
For example:
aFun :: Int -> Int
bFun :: String -> Bool
cFun :: Char -> Char -> String
aFun takes an Int and returns an Int
bFun takes a String and returns a Bool
cFun takes two Chars and returns a String
BB1756: SWD 38
Why You Should Love Types! Why You Should Love Types!
For example:
aFun :: Int -> Int
bFun :: String -> Bool
cFun :: Char -> Char -> String
dFun :: (Float,Float) -> String
aFun takes an Int and returns an Int
bFun takes a String and returns a Bool
cFun takes two Chars and returns a String
dFun takes a pair of Floats and returnsa String
BB1756: SWD 39
Why You Should Love Types! Why You Should Love Types!
The second reason why you should love types is that:
anybody who wants to use the functions in the futureknows what they require as input and return as output.
Often all that one wants to know about a function that one wantsto reuse is the type(s) of its input, the type of its output, and whatthe function does.
That is, one doesn’t need to know how the function does what it does.
BB1756: SWD 40
Why You Should Love Types! Why You Should Love Types!
For example:
fFun str = addOne (length str)
BB1756: SWD 41
Why You Should Love Types! Why You Should Love Types!
For example:
fFun :: String -> IntfFun str = addOne (length str)
The input to fFun is a String and theoutput is an Int. Since length can be applied to a String and returns its length as an Int , and addOne is applied to an Int, this is OK.
We do not care how length is defined!
BB1756: SWD 42
Why You Should Love Types! Why You Should Love Types!
For example:
gFun s i = i == length s
BB1756: SWD 43
Why You Should Love Types! Why You Should Love Types!
For example:
gFun :: String -> Int -> BoolgFun s i = i == length s
The inputs to gFun is a String and anInt. The output is a Bool.length can be applied to a String andreturn an Int.== takes two values (of the same type)and returns a Bool.
We do not care how length and== are defined!
BB1756: SWD 44
Why You Should Love Types! Why You Should Love Types!
The third reason why you should love types is that:
they allow the compiler (e.g. Hugs) to spot errors inthe function definition.
That is, the input(s) and output of the function are specified by typesand the definition needs to be consistent with this.
Note: This is called a compile-time error.
BB1756: SWD 45
Why You Should Love Types! Why You Should Love Types!
For example:
hFun :: String -> InthFun x = x + 99
BB1756: SWD 46
Why You Should Love Types! Why You Should Love Types!
For example:
hFun :: String -> InthFun x = x + 99
The input to hFun is a String and theoutput is an Int. The definition tries to add a Stringto 99 which will result in a compile-timeerror.
BB1756: SWD 47
Why You Should Love Types! Why You Should Love Types!
For example:
hFun :: String -> InthFun x = x + 99
iFun :: (Char, Char) -> BooliFun c1 c2 = c1 == c2
The input to hFun is a String and theoutput is an Int. The definition tries to add a Stringto 99 which will result in a compile-timeerror.
BB1756: SWD 48
Why You Should Love Types! Why You Should Love Types!
For example:
hFun :: String -> InthFun x = x + 99
iFun :: (Char, Char) -> BooliFun c1 c2 = c1 == c2
The input to hFun is a String and theoutput is an Int. The definition tries to add a Stringto 99 which will result in a compile-timeerror.
The input to iFun is a pair of Chars.The definition uses two Chars.This is not the same and thus a compile-time error!
BB1756: SWD 49
Why You Should Love Types! Why You Should Love Types!
For example:
hFun :: String -> InthFun x = x + 99
iFun :: (Char, Char) -> BooliFun c1 c2 = c1 == c2
jFun :: String -> Int -> BooljFun s i = if length s == i
then “Same”else “Different”
The input to hFun is a String and theoutput is an Int. The definition tries to add a Stringto 99 which will result in a compile-timeerror.
The input to iFun is a pair of Chars.The definition uses two Chars.This is not the same and thus a compile-time error!
BB1756: SWD 50
Why You Should Love Types! Why You Should Love Types!
For example:
hFun :: String -> InthFun x = x + 99
iFun :: (Char, Char) -> BooliFun c1 c2 = c1 == c2
jFun :: String -> Int -> BooljFun s i = if length s == i
then “Same”else “Different”
The input to hFun is a String and theoutput is an Int. The definition tries to add a Stringto 99 which will result in a compile-timeerror.
The input to iFun is a pair of Chars.The definition uses two Chars.This is not the same and thus a compile-time error!
The input to jFun is a String and an Int.The output is a Bool.The output in the definition is a String.This clashes with the specification andthus is a compile-time error!
BB1756: SWD 51
Why You Should Love Types! Why You Should Love Types!
The fourth reason why you should love types is that:
they allow errors to be identified when the functionis actually used.
That is, if one tries to apply a function to the incorrect input thenthe type specification will highlight this error.
Note: This is called a runtime error.
BB1756: SWD 52
Why You Should Love Types! Why You Should Love Types!
For example:
hugs:> length 7
hugs:> snd “Dan” True
hugs:> double True
BB1756: SWD 53
Why You Should Love Types! Why You Should Love Types!
For example:
hugs:> length 7
hugs:> snd “Dan” True
hugs:> double True
The input to length is a String.Here we are trying to apply it to an Intwhich results in a runtime error.
BB1756: SWD 54
Why You Should Love Types! Why You Should Love Types!
For example:
hugs:> length 7
hugs:> snd “Dan” True
hugs:> double True
The input to length is a String.Here we are trying to apply it to an Intwhich results in a runtime error.
The input to snd is a pair of values.Here we are trying to apply it to two values which results in a runtime error.
BB1756: SWD 55
Why You Should Love Types! Why You Should Love Types!
For example:
hugs:> length 7
hugs:> snd “Dan” True
hugs:> double True
The input to length is a String.Here we are trying to apply it to an Intwhich results in a runtime error.
The input to snd is a pair of values.Here we are trying to apply it to two values which results in a runtime error.
The input to double is an Int.Here we are trying to apply it a Boolwhich is a runtime error.
BB1756: SWD 56
Why You Should Love Types! Why You Should Love Types!
The final reason why you should love types is that:
without them all of the above benefits would disappear.
That is, -- erroneous code would compile!
-- one could apply functions to inappropriate inputs and something (unexpected) would happen!
-- potential users of functions would have no idea how they should be used!