domingo, 26 de abril de 2015

Introduction

I have always been fascinated by computer programming. My appetite was whetted ever since I was exposed to languages such as BCPL, C, Snobol, Lisp, Prolog and many more. In my efforts to sharpen my problem-solving skills in Project Euler (https://projecteuler.net/) I noticed many persons using Haskell and this made me curious. I got into Haskell and now with this blog I am documenting that journey.My recent forage into Haskell has also been driven by my curiosity as to its usefulness as a teaching tool for Linear Algebra. As a functional language it should facilitate this so this is my quest. If you need additional motivation to learn Haskell, read this from eWeek.

I though once of writing a text but then cme across some great texts and that stumped me so I have decided just on recording these steps in the hope that they may be helpful to some other newbie like myself. As I go, I shall be updating this blog.  Learning a new language is fun and I recommend it! Let's go.

Reference Texts

These texts are really great. Take time to read them all...
You will be very happy!

Functional programming

Haskell is an advanced purely functional programming language. You can dabble a bit on the URL
https://www.haskell.org/ and while the code looks strange at first, we need to really get used to it to be able to make the most of it.

What is functional programming?

From this website http://www.functionalprogramming.com/, I have selected this definition:

In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state. Functional programming has its roots in lambda calculus, a formal system developed in the 1930s to investigate function definition, function application, and recursion. Many functional programming languages can be viewed as elaborations on the lambda calculus.

Haskell Platform


In order to be able to use your computer to run Haskell code, you would have to download and install the Haskell platform: This can be done best from:https://www.haskell.org/downloads.

https://www.haskell.org

I have so far only experimented using Windows systems (Windows 7 and Windows 8). No doubt the processes are simple on Linux and OS based systems as well. This provides you with a development environment in which you can run code at the command prompt as well as load code from files in folders on your hard drive or wherever. There is a text editor in the IDE as well but I preferred to use Notepad++ (http://notepad-plus-plus.org/).

The system installed is the Glasgow Haskell Compiler (GHC) and the prompt is the Prelude> which you can change if you really want to but in my case I haven't done so. It does not take long to get used to the environment and within a few minutes you are up and running. I tend to use the WinCHCi and I have made a shortcut on my Windows 7 desktop so I can easily get into this system.

Introduction to Haskell

As a great first introduction to Haskell, I recommend "Learn You a Haskell for Great Good" which is available online at the URL  http://learnyouahaskell.com/. Read the text and practice the exercises so you get a good feel for the language and the environment as well. I did find that some of the interactive suggestions did not work but you always have to look for a go-around.

Once you have downloaded and installed the Haskell Integrated development Environment, you would be able to interact with it:

As you start to dabble in Haskell, it is best always to start with the interactive mode. Follow suggestions from the literature and try this and try that. I did some simple arithmetic and then went into some simple functions and just trying and trying and trying. This gives you a feel for what works even before you delve into the language definition itself.

Here are some suggestions:

Simple arithmetic using both infix and prefix notation:

Prelude> 5 + 4
Prelude> (+) 5 4
Prelude> 5/4

Expression Evaluation

Prelude>7 * 8 + 3

Assignments

We can assign a value to a variable x using the "let" statement

Prelude> let x = 4

and test that the variable x has been assigned the value as follows:

Prelude> x

Built-in Functions

Haskell has libraries of built-in functions such as exp which computes the exponent of an argument.

Prelude> exp 3 

This yields
 20.085536923187668

You can check that out using your favourite calculator!


Lists

We can create a list with two members 1 and 3 as follows:

Prelude>[1, 2]

and add a new member to the front of the list using the : operator

Prelude> 0 : [1, 2]
[0, 1, 2]


You can also use built-in functions such as length as follows:

Prelude> length [0, 1, 2]
3

We can even create lists of ordered pairs:

Prelude> [(n, 2 * n) |  n  <-  [1..5]]
[(1,2),(2,4),(3,6),(4,8),(5,10)]
Prelude>

That is, we want the list of ordered pairs for which the first element is n for n = 1 ..5 and the second is 2 * n.


Functions

We can construct some simple functions:

Prelude>let sq x = x * x

and test it using:

Prelude> sq 3

As you create more and more functions be careful not to use function names which already exist such as exp which is an in-built function.

Prelude>let myadd a b = a + b
Prelude>myadd 3 4

so that before embarking on writing "programs" one has a sense of what works and what does not work.

As you start creating simple sample programs, it is best to have them all stored in a folder. In my case, I created a folder called "Haskel" in my "Documents" and always store my code there.

Don't be too fast to run away from the interactive mode as for instance you can do something like the following:

Prelude> let isEven n = if mod n 2 == 0 then "yes!" else "no!"
Prelude>
isEven 5
"no!"


or even try printing the first five factorials


Function Composition

Given that Haskell is a functional programming language, you would expect that it supports function composition. It does!

Prelude> let f x = x * x
Prelude> let g x = 3 * x
Prelude> (f.g) 5
225
Prelude>  

Prelude> print [ (n, product [1..n]) | n <- [1..5]]
[(1,1),(2,2),(3,6),(4,24),(5,120)]


Can you make sense of the code in each of these instances?

So clearly the interactive mode is quite useful for helping us get into the language constructs and testing these before we actually use them in a program.

A program is a set of source code instructions which is saved in a file and loaded into the IDE and subsequently compiled and executed. In Haskell, program sub-components are divided into modules. We shall see more of that later. For the moment, we shall use only the Main module.

Hello, World!


Traditionally, the very first program one writes in a language is the "Hello, World" program:

 module Main
      where

main = putStrLn "Hello World"


This is important as it points to system functionality. The code is entered into the Notepad++ editor and saved in a folder called Haskell. In the Haskell IDE, the code is loaded and then executed.


Note that it is also possible to compile the code and produce an executable file which could be run directly from the operating system.

Flop Program


The Haskell equivalent to the swap procedure in most languages is the flop:

flop (a, b) = (b, a)
main = print $ flop (1, "one")


and finally in this set of illustrations we shall look at a simple program to compute the hypotenuse of a right-angled triangle using Pythagoras' Theorem which is quite well known among school children:

module Main where

hypt a b = sqrt(a * a + b * b)

main :: IO ()
main = print $ hypt 3 4


This last illustration gives us a format for simple programs with the module Main and then the main statement which defines the execution point of the program.

2 plus 2

Here is another fairly simple program:

-- | 2 plus 2

main = do putStrLn "What is 2 + 2?"
          x <- readLn
          if x == 4
              then putStrLn "You're right!"
              else putStrLn "You're wrong!"


Can you guess what it is doing?

Try it in your Haskell IDE.

Grocery List

Let's suppose we were asked to add up a set of prices in a grocery list. Maybe a set such as

23
45
67
89
12
11

How would you approach that?

nums = [
        23,
        45,
        67,
        89,
        12,
        11
        ]

main = print $ sum nums


Haskell Programming Tips


In this section, we shall look at some Haskell programming tips"

Indentation

In Haskell the indentation is important. Haskell uses a system called layout to automatically block its code so that statements within a block must have the same indentation.


Comments

Comments in Haskell start with --  as you can see from the "2 plus 2" program above. Comments are an important source of information within the code and would help to remind you of details of algorithms used and even persons responsible for different modules and parts of the source code. I tend to use comments at the beginning of the program to remind me of the file name, programmer and date of writing of the code as well.


Functions

You may have noted that all function names start with a common letter.Haskell requires that all function names and values start with common letters. The names given to types begin with a capital letter.


Modules


In Haskell, a program consists of a collection of modules. Modules help us divide up the code into manageable segments.  Module names are alphanumeric and must begin with a capital letter. We have been using the module Main.Modules must be imported for the functions to be used. As an example of the use of modules, consider the use of the module Data.List

Prelude> import Data.List
Prelude Data.List> sort [2, 1, 3]
[1,2,3]
Prelude Data.List> transpose [[1,2,3],[4,5,6],[7,8,9]]
[[1,4,7],[2,5,8],[3,6,9]]
Prelude Data.List> takeWhile (>3) [6,5,4,3,2,1,2,3,4,5,4,3,2,1]
[6,5,4]
Prelude Data.List> sort [8,5,3,2,1,6,4,2]
[1,2,2,3,4,5,6,8]
Prelude Data.List> group [1,1,1,1,2,2,2,2,3,3,2,2,2,5,6,7]
[[1,1,1,1],[2,2,2,2],[3,3],[2,2,2],[5],[6],[7]]
Prelude Data.List> partition (>3) [1,3,5,6,3,2,1,0,3,7] 
([5,6,7],[1,3,3,2,1,0,3])
Prelude Data.List> find (>4) [1,2,3,4,5,6] 
Just 5
Prelude Data.List> [1..7] `intersect` [5..10]
[5,6,7]
Prelude Data.List> insert 4 [3,5,1,2,8,2]
[3,4,5,1,2,8,2]
As we learn Haskell, we have to also familiarise ourselves with what is in the various modules. We can even write our own modules as well.

Input and Output

 Already in the program samples above you can see instances of both input and output. With the input statements we can enter arguments directly from the keyboard at run time while the output helps us see what the computed results are. The program "2 pls 2" has both input and output and is a good example.

Indentation

Readability of the code is another important facet of programming. It is necessary in Haskell and identifies the  various parts of the control segments of the program. Also, white spaces are important for both readability as well as the organisation of the code.

Functions


Some Simple Programs

In the following, we shall explore some simple programs to get used to Haskell as well as the environment in which we are working:

MyAdd

One of the most useful mathematical operations is undoubtedly the addition and here is a little program that defines "myadd" - my own definition of addition which of course does not differ from what we know as addition: It uses the same program structure as the program Pythagoras and also the Hello World. Note that we have defined a function called myadd inside the module Main and then a variable z to hold the result which we print out.

module Main where

myadd a b = a + b

main :: IO ()
main = do let z = myadd 5 3
          putStrLn $ "The result is: " ++ show z



Exercises:

  1. Try this program in your Haskell IDE and then edit it so that instead of addition, it does subtraction ,multiplication and division.
  2. Save each as a separate program in your folder. For each add it a comment as the first line just stating the file name and what the program does.
  3. make a copy of each of the programs and for each arrange that instead of the parameters of the function being supplied at compile time that they are supplied at run time. Yoou may need to make reference to the program "2 plus 2" for this.

Have fun!


Factorial n


From our high school mathematics, we may be familiar with the factorial of a number n say (written n!). We know that

n! = n . (n-1).(n-2) ...3.2.1

So for instance 3! = 3.2.1 and 30! = 30.29.28....3.2.1

We can always visualise an abstraction better if we use concrete examples and also simple examples too. Now to be able to code this we see that

n! = n.(n-1)!

This gives us an idea! The problem is: is this idea supported in the programming language? In Haskell it is.  The idea of using a function in its own definition is called recursion and Haskell can handle this so let's see how we may be able to do it:

module Main
    where

fac 0 = 1
fac n = n * fac (n-1)

main = print (fac  3)



Exercises

  1. Try this. What result did Haskell provide? Does this match your expectations?
  2. Again, arrange for the parameter to be entered at run time from the keyboard.
  3. Create a table of "test" values (about five) and run your program for each of these values while hand computing the answers. Compare. What does this tell you about your code?

Note: An important facet in programming is testing your code. While you make every effort to program correctly, your program must be tested before being put into production. As a rule, you should select your test data so that it provides some indication of the operation of your program both under normal input as well as input which would test its limiting conditions.


Multiplication (Recursive addition)


It does not have to be a complicated problem for us to apply recursion. Consider the following multiplication done by using a recursive addition:

module Main where

mult a 1 = a
mult a b = a + mult a b-1

main :: IO ()
main = do let z = mult 5 3
          putStrLn $ "The result is: " ++ show z


Exercise

  1. Run this program.
  2. Test it out with several parameters of your choice.


Fibonacci Sequence

You may have heard of the Fibonacci Sequence. This is a sequence of numbers as follows:


1, 1, 2, 3, 5, 8, 13, 21, 34, ...

The first and second numbers are both equal to 1 The next number is found by adding up the two numbers before it.
  • The 2 is found by adding the two numbers before it (1+1)
  • Similarly, the 3 is found by adding the two numbers before it (1+2),
  • And the 5 is (2+3),
  • and so on!
So what is the 10th number in the sequence?

We can set Haskell to the task as follows:

module Main
    where

fib 1 = 1
fib 2 = 1
fib n = fib (n - 1) + fib (n-2)

main :: IO ()
main = print (fib 10)



Exercise

  1. Run this program. What is the result?
  2. Try hand computing the fib (10) and see how your result matches with the computer generated result.
  3. Now we feel confident we can predict the 20th number. What is it?
  4. Try fib(30), fib (40) and fib (50)

Have fun!

The output of the previous programs would probably look like:


To make adjustments to the code which is already loaded you can use the built-in text editor:



You may realise that the output of the previous program is deficient in some respect. What is it? You may also have realised that it took some time to compute fib (40). Were you able to do fib(50)?

What if you were doing some research into Fibonacci Numbers for a mathematical project and you had to compute fib(1000)? This computational complexity is hat you would eventually have to be able to reduce by using smart algorithms. We cannot afford to tie up the CPU for such a long time and especially if you are in a commercial environment where you are paying for CPU time. Fortunately Haskell is a lazy language (it only computes what it really has to) so we can use this to our advantage.


Exercise
  1. Arrange for a user prompt to enter the required parameter.
  2. Create a table showing the parameters and the time taken for the computation
  3. draw a rough sketch showing the increase in time for parameters of 5, 10, 15, 20, 25, 30,..50

Have fun!


Multiple of 3 and 5


Consider the following problem which was one of the problems posed in Project Euler:

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000.

As simple solution from elementary set theory would be to get the sum of all multiples of 3 and the sum of all multiples of 5 and then subtract those that are multiples of both 3 and 5 as we would have counted this set in twice.  Try this for the same problem up to say a limit of 20:

multiples of 3 = {3, 6, 9, 12, 15, 18}
multiples of 5 ={5, 10, 15}
multiples of 3 and 5 = {15}

sum of multiples of 3 = 63
sum of multiples of 5 = 30
sum of multiples of 3 and 5 = 15

Hence sum of multiples of 3 and 5 less than 20 = 63 + 30 - 15 = 78

We can make Haskell work this out for us as in the following:

Prelude> sum [n | n <- [1..20-1], n `mod` 5 == 0 || n `mod` 3 == 0]
78
Prelude> 

and using this we can solve the problem in the Project Euler easily with

Prelude> sum [n | n <- [1..1000-1], n `mod` 5 == 0 || n `mod` 3 == 0]

The Project Euler (https://projecteuler.net/about) is a great source of problems to sharpen your problem solving skills. Not all the problems will be quite as easy as the one shown but you will get hooked on problem solving and the problems are challenging! Try it!


Even Fibonacci Numbers


Try sussing out a plan by hand for the solution of the second problem in Project Euler.

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.



Euclid's GCD Algorithm


Another problem usually tacked early in a course in programming is Euclid's GCD algorithm. The problem context can be gleaned from the Cut-the-Knot website: http://www.cut-the-knot.org/blue/Euclid.shtml. The idea is that the GCD of two numbers, represented by

gcd (25, 15) = 5  so 5 is the highest number that divides into both 15 and 25.



The algorithm computes the Greatest Common Divisor (GCD) of two integers.

We have seen that the algorithm works basically as:

gcd (x, y) = gcd (y, remainder of x/y) y > 0
gcd (x, y) = x, y = 0

Where both x and y are non-negative integers.

Testing:

gcd (x, y)
gcd (y, x%y)
y >0
Output
gcd (15, 10)
gcd (10, 5)
true

gcd(10, 5)
gcd (5, 0)
true

gcd(5,0)

false
5


The Haskell program to produce the solution is:


module Main where

mygcd a 0 = a
mygcd a b = mygcd b (a `mod` b)

main :: IO ()
main = do let z = mygcd 15 25
          putStrLn $ "The gcd of 15 and 25 is: " ++ show z



This is a fairly complicated set of code and so what we should do as part of the testing process is do a dry run of the code. In the dry run, we will select a  set of test data and follow the values assigned to the various variable locations.


Dry Run


let n = 34
let m = 20

32 = 1.20 + 12
20 = 1.12 + 8
12 = 1.8 + 4
8 = 2.4 + 0

Thus, gcd (34, 20) = 2

  • Can you describe this algorithm in some way that would make it clearer?

Observe that while the remainder is non-zero, move the m number to where the n number is and look for divisors of the remainder. The scenario is somewhat clearer when we lay it out as follows:

temp
n
m
n % m

34
20
14
34
20
14
6
20
14
6
2
14
6
2
0



Exercise
  1. Run this program using several sets of test data.
  2. How do the results of the run compare with your own computations?

Have fun!

Files

In programming, we will inadvertently come across files and file input and output.

Create a small text file called "foo.txt"

In my case, I have created a file with the contents:

abc
def
ghi
jlk
mno

and saved it in the same directory where I shall save my file-input code.

Now create a file called "file-input-1.hs" as follows:

-- | file-input-1.hs

import qualified Data.ByteString as Str

main = do contents <- Str.readFile "foo.txt"
          Str.putStr contents


Run the code:



This is not the only way we cold have written our file-input program.


Classes

Manipulating file I/O

Modules

Here we will look at some modules...

viernes, 24 de abril de 2015

Problem Solving

In this section, we shall look at some problem solving issues. We will start with some problems which have already been posed but which still do pose some issues.


Factorial n


From our high school mathematics, we may be familiar with the factorial of a number n say (written n!). We know that

n! = n . (n-1).(n-2) ...3.2.1

So for instance 3! = 3.2.1 and 30! = 30.29.28....3.2.1

We can always visualise an abstraction better if we use concrete examples and also simple examples too. Now to be able to code this we see that

n! = n.(n-1)!

This gives us an idea! The problem is: is this idea supported in the programming language? In Haskell it is.  The idea of using a function in its own definition is called recursion and Haskell can handle this so let's see how we may be able to do it:

module Main
    where

fac 0 = 1
fac n = n * fac (n-1)

main = print (fac  3)



Exercises

  1. Try this. What result did Haskell provide? Does this match your expectations?
  2. Again, arrange for the parameter to be entered at run time from the keyboard.
  3. Create a table of "test" values (about five) and run your program for each of these values while hand computing the answers. Compare. What does this tell you about your code?

Note: An important facet in programming is testing your code. While you make every effort to program correctly, your program must be tested before being put into production. As a rule, you should select your test data so that it provides some indication of the operation of your program both under normal input as well as input which would test its limiting conditions.



Fibonacci Sequence

You may have heard of the Fibonacci Sequence. This is a sequence of numbers as follows:


1, 1, 2, 3, 5, 8, 13, 21, 34, ...

The first and second numbers are both equal to 1 The next number is found by adding up the two numbers before it.
  • The 2 is found by adding the two numbers before it (1+1)
  • Similarly, the 3 is found by adding the two numbers before it (1+2),
  • And the 5 is (2+3),
  • and so on!
So what is the 10th number in the sequence?

We can set Haskell to the task as follows:

module Main
    where

fib 1 = 1
fib 2 = 1
fib n = fib (n - 1) + fib (n-2)

main :: IO ()
main = print (fib 10)



Exercise
  1. Run this program. What is the result?
  2. Try hand computing the fib (10) and see how your result matches with the computer generated result.
  3. Now we feel confident we can predict the 20th number. What is it?
  4. Try fib(30), fib (40) and fib (50)

Have fun!

You may realise that the output of the previous program is deficient in some respect. What is it? You may also have realised that it took some time to compute fib (40). Were you able to do fib(50)?

What if you were doing some research into Fibonacci Numbers for a mathematical project and you had to compute fib(1000)? This computational complexity is hat you would eventually have to be able to reduce by using smart algorithms. We cannot afford to tie up the CPU for such a long time and especially if you are in a commercial environment where you are paying for CPU time. Fortunately Haskell is a lazy language (it only computes what it really has to) so we can use this to our advantage.


Exercise
  1. Arrange for a user prompt to enter the required parameter.
  2. Create a table showing the parameters and the time taken for the computation
  3. draw a rough sketch showing the increase in time for parameters of 5, 10, 15, 20, 25, 30,..50

Have fun!


Multiple of 3 and 5


Consider the following problem which was one of the problems posed in Project Euler:

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000.

As simple solution from elementary set theory would be to get the sum of all multiples of 3 and the sum of all multiples of 5 and then subtract those that are multiples of both 3 and 5 as we would have counted this set in twice.  Try this for the same problem up to say a limit of 20:

multiples of 3 = {3, 6, 9, 12, 15, 18}
multiples of 5 ={5, 10, 15}
multiples of 3 and 5 = {15}

sum of multiples of 3 = 63
sum of multiples of 5 = 30
sum of multiples of 3 and 5 = 15

Hence sum of multiples of 3 and 5 less than 20 = 63 + 30 - 15 = 78

We can make Haskell work this out for us as in the following:

Prelude> sum [n | n <- [1..20-1], n `mod` 5 == 0 || n `mod` 3 == 0]
78
Prelude> 

and using this we can solve the problem in the Project Euler easily with

Prelude> sum [n | n <- [1..1000-1], n `mod` 5 == 0 || n `mod` 3 == 0]

The Project Euler (https://projecteuler.net/about) is a great source of problems to sharpen your problem solving skills. Not all the problems will be quite as easy as the one shown but you will get hooked on problem solving and the problems are challenging! Try it!


Even Fibonacci Numbers

Try sussing out a plan by hand for the solution of the second problem in Project Euler.

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.


Euclid's GCD Algorithm

Another problem usually tacked early in a course in programming is Euclid's GCD algorithm. The problem context can be gleaned from the Cut-the-Knot website: http://www.cut-the-knot.org/blue/Euclid.shtml. The idea is that the GCD of two numbers, represented by

gcd (25, 15) = 5  so 5 is the highest number that divides into both 15 and 25.


The algorithm computes the Greatest Common Divisor (GCD) of two integers.

We have seen that the algorithm works basically as:

gcd (x, y) = gcd (y, remainder of x/y) y > 0
gcd (x, y) = x, y = 0

Where both x and y are non-negative integers.

Testing:

gcd (x, y)
gcd (y, x%y)
y >0
Output
gcd (15, 10)
gcd (10, 5)
true

gcd(10, 5)
gcd (5, 0)
true

gcd(5,0)

false
5


The Haskell program to produce the solution is:


module Main where

mygcd a 0 = a
mygcd a b = mygcd b (a `mod` b)

main :: IO ()
main = do let z = mygcd 15 25
          putStrLn $ "The gcd of 15 and 25 is: " ++ show z



This is a fairly complicated set of code and so what we should do as part of the testing process is do a dry run of the code. In the dry run, we will select a  set of test data and follow the values assigned to the various variable locations.


Dry Run


let n = 34
let m = 20

32 = 1.20 + 12
20 = 1.12 + 8
12 = 1.8 + 4
8 = 2.4 + 0

Thus, gcd (34, 20) = 2

  • Can you describe this algorithm in some way that would make it clearer?

Observe that while the remainder is non-zero, move the m number to where the n number is and look for divisors of the remainder. The scenario is somewhat clearer when we lay it out as follows:

temp
n
m
n % m

34
20
14
34
20
14
6
20
14
6
2
14
6
2
0



Exercise
  1. Run this program using several sets of test data.
  2. How do the results of the run compare with your own computations?

Have fun!