Introduction to Haskell

GHCi is installed on tux.cs.drexel.edu. You can run it by typing ghci.
You can download and install Haskell from http://www.haskell.org/ghc/

To exit Haskell, type Ctrl-D or :quit.
To load a file in the current directory type :load "filename".
To load maxmin.hs from the current directory
:load maxmin.hs

The Basic math functions work as expected.
Prelude> 9*10
90
Prelude> 9 + 8
17
Prelude> 10-20
-10
Prelude> 4 < 5
True
Prelude> 10-1.1
8.9

We can assign variables and functions using the let syntax. We can also import them in files.
Defining Variables: Prelude> let x = 42
Prelude> x+10
52
Defining Functions: Prelude> let gcd1 u v = if v == 0 then u else gcd1 v (mod u v)
Prelude> gcd1 100 15
5
The :{ syntax can be used to write commands that span multiple lines.
Prelude> :{
Prelude| let { fact 0 = 1
Prelude| ; fact n = n * fact (n-1)
Prelude| }
Prelude| :}
Prelude> fact 10
3628800

Defining functions in files and loading them is simple.
Example File fact.hs

fact 0 = 1
fact n = n * fact ( n-1)
square x = x * x
gcd1 u v = if v == 0 then u else gcd1 v (mod u v)
reverse1 [] = []
reverse1 (h:t) = reverse1 t ++ [h]
        
After creating the file we can load and run it.
Prelude> :load fact.hs
[1 of 1] Compiling Main ( fact.hs, interpreted )
Ok, modules loaded: Main.
*Main> fact 34
295232799039604140847618609643520000000

All functions in Haskell are curried. This means we can create new functions by not giving all the inputs to existing funtions.
To make a plus 1 function all we have to do is add 1 without a second argument.
*Main> let plus1 = (1+)
A higher-Order Function example uses map
*Main> let square_list = map (\x -> x * x)
The backslash sytanx creates a lambda function. In this example, we don't need to give our squaring function a name.
*Main> square_list [1,2,3,4,5]
[1,4,9,16,25]

The function composition operator (dot .) can be used to combine functions.
*Main> let secretfunction = ((*3) . (2+))
*Main> secretfunction 5
21

List Commands
Add an element to the front of a list
1 : [2,3,4]
Merge Two Lists
[1,2,3] ++ [4,5,6]
Get the first element in a list
head [1,2,3]
Get the rest of the list
tail [1,2,3]
Just like in ML, we can use pattern matching to save on head/tail calls.
let (h:t)=[1,2,3,4]
Test for a null list
null []
Haskell has a special syntax for writing functions of list. This is a shorthand for map calls.
let square_list list = [ x * x | x <- list]

Haskell uses lazy evaluation, meaning all values are delayed until needed. This makes it very useful for working with infinite lists. We get the same functionality as delay/force built in to all lists.
We can create a list with an infinite number of ones.
let ones = 1 : ones
Then we can take as many as we want
take 30 ones
The take command takes the first n elements from a list.
The drop command removes the first n elements from a list, leaving you with the remaining list.
The below command removes the first 4 values from a list then takes the next 5. The list [2..] is the set of integers starting at 2.
*Main> take 5 (drop 4 [2..])
[6,7,8,9,10]

The Sieve of Eratosthenes
The idea behind the sieve is that it takes all integers and filters out those that are not prime. This gives an infinite list of the primes.
let sieve (p:lis) = p : sieve [n | n <- lis, mod n p /= 0]
*Main> let primes = sieve [2..]
*Main> take 100 primes
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139, 149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283, 293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457, 461,463,467,479,487,491,499,503,509,521,523,541]

With a list of all the primes, we can filter it again to find twin primes. A twin prime is a prime p where either p+2 or p-2 is also prime.
Since we know the list of primes is ordered, it is easy to know when a search should stop.
let orderedSearch a (h:t) = if a < h then False else (if a == h then True else orderedSearch a t )
A number is a twin prime if either p+2 or p-2 is found in the list of primes. We assume that the value a will be prime. We could check, but since we know the list we are filtering is only primes it is unnecessary.
let isTwinPrime a = (orderedSearch (a+2) primes) || (orderedSearch (a-2) primes)
Finally, we fitler the list of primes for only twin primes.
let tprimes = filter isTwinPrime primes
The first 21 twin primes can be shown *Main> take 21 tprimes
[3,5,7,11,13,17,19,29,31,41,43,59,61,71,73,101,103,107,109,137,139]

You can download these functions primes.hs