Prelude.hs

Prelude.hs is the standard library which is loaded when you start Haskell, and it contains all the functions you have learned so far. Here's my pick of the most useful. Note that just knowing about these functions ain't gonna help you; knowing how to use them is the key! So, lots of practice is essential.

List processing basics
 (:) (list constructor) ++ head last tail init length !! (list index)

Extra list processing
 maximum minimum reverse elem notElem concat take drop takeWhile dropWhile words unwords

Arithmetic
 div mod gcd lcm even odd sum product

Higher Order Functions
Map, fold and filter are so powerful, they've been put on their own page instead.

Tuples
 zip unzip fst snd

Other functions

List processing basics

No examples needed here I hope :)

1 - :

The basic list constructor. Adds an element to the front of a list.

2- ++
The list concatenator. Adds a list onto the front of another list. Make sure you understand the difference between : and ++

Returns the first element of a list.

4 - last
The opposite of head; last returns the last element of a list.

5 - tail
The tail of a list is everything except the first element. Returns an error if the list is empty.

6 - init
The opposite of tail. Given a list, init returns the list without the last element.

7 - length
Returns the length of the list

8 - !!
Returns the element of a list located at the specified index. Note that an 'index' starts counting from zero.

Extra List Processing

1 - maximum and minimum
These return the largest and smallest elements of a list repectively. Don't worry too much about the Ord a part of the type signature, but if you must know, then it means that this function only takes inputs of a Type which is deriving Ord. (1) That means that Haskell knows how to put these things in Order. (e.g. 1 < 2, 2 < 5, 'a' < 'z', False < True)

Prelude> :t maximum maximum :: Ord a => [a] -> a Prelude> :t minimum minimum :: Ord a => [a] -> a Prelude> maximum ['a'..'z'] 'z' Prelude> maximum [True, True, False] True Prelude> minimum ["ABCD", "ABCE", "ABC"] "ABC"

2 - reverse
reverse takes a list and, um, reverses it

Prelude> :t reverse reverse :: [a] -> [a] Prelude> reverse [1..10] [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] Prelude> reverse ['a'..'k'] "kjihgfedcba"

3 - elem and notElem
elem tells you if a specified element is in a list, and notElem is simply the opposite of that. Note that this only works for types which are deriving Eq, (2) meaning that Haskell knows how to say "that element is the same as this one".

Prelude> :t elem elem :: Eq a => a -> [a] -> Bool Prelude> :t notElem notElem :: Eq a => a -> [a] -> Bool Prelude> elem 'a' "milkshake" True Prelude> notElem 'a' "milkshake" False Prelude> elem "ABC" ["ABCD", "AB", "CBA"] False

4 - concat
concat takes in a list of lists and combines them all into one list. (3)

Prelude> :t concat concat :: MonadPlus a => [a b] -> a b (Think of this as [[a]] -> [a] Prelude> concat ["ABCD", "AB", "CBA"] "ABCDABCBA"

5 - take and drop
take n [a] gives you the first n elements of the list. Likewise, drop n [a] gives you everything back except the first n elements of a list.

Prelude> :t take take :: Int -> [a] -> [a] Prelude> :t drop drop :: Int -> [a] -> [a] Prelude> take 4 "milk - legendary stuff" "milk" Prelude> drop 6 "milk - legendary stuff" " legendary stuff" Prelude> (take 4 string) ++ " is" ++ (drop 6 string) where string = "milk - legendary stuff" "milk is legendary stuff"

(Yes, you can type 'where' clauses into Haskell!)

6 - takeWhile and dropWhile
takeWhile and dropWhile are similar to normal take and drop, but are more powerful - they take in a function (only certain types though) and uses it to 'test' elements of the list starting from the beginning. It will continue to take or drop elements from the list until an element fails the test.

The function you feed takeWhile or dropWhile must be of type (a -> Bool). That is, it takes one input of any type and returns a Bool. Examples of valid functions are isVowel (which you wrote) or the inbuilt functions isUpper, isLower, isDigit, even, odd. Less obvious but most useful are (==) and (>) and (<).

Prelude> :t takeWhile takeWhile :: (a -> Bool) -> [a] -> [a] Prelude> :t dropWhile dropWhile :: (a -> Bool) -> [a] -> [a] Prelude> takeWhile (<=4) [1..10] [1, 2, 3, 4] Prelude> takeWhile (isDigit) "5984357one2three234" "5984357" Prelude> dropWhile (isDigit) "5984357one2three234" "one2three234"

7 - words and unwords
words takes in a single String and breaks it up wherever there are spaces, into a list of Strings. And unwords does the opposite.

Prelude> :t words words :: String -> [String] Prelude> :t unwords unwords :: [String] -> String Prelude> words "this is a cgi string after you decode it" ["this", "is", "a", "cgi", "string", "after", "you", "decode", "it"] Prelude> unwords ["this", "is", "a", "cgi", "string", "after", "you", "decode", "it"] "this is a cgi string after you decode it"

Arithmetic

1 - `div` and `mod`
`div` is how many whole times the first number can be divided by the second number. `mod` is the remainder after the first number is divided by the second number. Note that `div` and `mod` only process integers.(4)

Prelude> :t div div :: Integral a => a -> a -> a Prelude> :t mod mod :: Integral a => a -> a -> a Prelude> 17 `mod` 6 5 Prelude> 17 `div` 6 2

2 - gcd and lcm
gcd stands for Greatest Common Divisor of two numbers. lcm is the Lowest Common Multiple of two numbers. Useful for some Discrete Mathematics algorithms, but not much else.

Prelude> :t gcd gcd :: Integral a => a -> a -> a Prelude> :t lcm lcm :: Integral a => a -> a -> a Prelude> gcd 21 5 1 Prelude> gcd 21 14 7 Prelude> lcm 4 8 8 Prelude> lcm 12 8 24

3 - even and odd
How many times have you written isEven and isOdd, not realising that they were already inbulit?

Prelude> :t even even :: Integral a => a -> Bool Prelude> :t odd odd :: Integral a => a -> Bool Prelude> even 5 False Prelude> odd 5 True

3 - sum and product
Simply add up or multiply all the contents of a list of numbers

Prelude> :t sum sum :: Num a => [a] -> a Prelude> :t product product :: Num a => [a] -> a Prelude> sum [1..10] 55 Prelude> product [1..4] 24

Tuples

1 - fst and snd
fst and snd take in a two-element tuple and return the first and second element of that tuple respectively. They have a major drawback in that they only work for two-part tuples. HOWEVER it's an excellent idea to write your own versions of fst and snd for larger tuples when needed, like part2of5, part3of5, part4of5 and so on.
Prelude> :t fst fst :: (a,b) -> a Prelude> :t snd snd :: (a,b) -> b Prelude> fst ("Star", "Craft") "Star" Prelude> snd ("Star", "Craft") "Craft"
2 - zip and unzip
zip takes in two lists of (possibly different) things and turns them into a list of 2-element tuples. The first element of each of these tuples comes from the first list, and the second element comes from the second list. The length of this list equals the length of the smaller of the two lists. This is great for storing information which is related to another bit of data, such as Candidates and their number of Votes. And to reverse the process, you feed the tuples into unzip.
Prelude> :t zip zip :: [a] -> [b] -> [(a,b)] Prelude> :t unzip unzip :: [(a,b)] -> ([a],[b]) Prelude> zip "ABCD" [1,6,3,23,12] [('A', 1), ('B', 6), ('C', 3), ('D', 23)] Prelude> zip "ABCD" [1,6,3,23] [('A', 1), ('B', 6), ('C', 3), ('D', 23)] Prelude> zip [1,6,3,23] "ABCD" [(1, 'A'), (6, 'B'), (3, 'C'), (23, 'D')] Prelude> maximum (zip [1,6,3,23] "ABCD") (23, 'D') Prelude> snd (maximum (zip [1,6,3,23] "ABCD")) 'D' Prelude> unzip [(1, 'A'), (6, 'B'), (3, 'C'), (23, 'D')] ([1, 6, 3, 23], "ABCD")

Other functions

1 - show
show converts anything which has a Show function defined, into a String.

read is the opposite of show; it reads in a String and converts it to whatever type you specify. Note the way I've used it below!

3 - succ and pred
For types with an Enum function defined, succ gives the successor and pred gives the predecessor.

Prelude> :t succ succ :: Enum a => a -> a Prelude> :t pred pred :: Enum a => a -> a Prelude> succ 2 3 Prelude> succ 20 21 Prelude> pred 21 20 Prelude> succ 'Z' '[' Prelude> pred 'Z' 'Y' Prelude> succ "Letters" ERROR: [Char] is not an instance of class "Enum"

Footnotes

(1) This works for types deriving Ord (where Haskell works it out for you), or which have had Ord written by the user. Haskell normally puts elements in the order in which you typed them in. For example if you had

data TextNumber = One | Two | Four | Three
deriving Ord

Then Haskell would think that One is less than Two, Two is less than Four, and Four is Less than Three. Solution: type them in properly or write your own Ord function.

(2) Likewise, you can let Haskell define Eq automatically (deriving Eq) or you can write your own. This is true for all classes (Eq, Ord, Enum, Show, Read ...)

(3) Monads are complicated.... and not studied in COMP1011.

(4) `div` and `mod` are examples of what are called "infix" operators. That is, you can put the function name between the inputs in forward quotes.
So 17 `div` 6 is exactly the same as div 17 6. Use whichever you are more comfortable with (probably the infix version).

paull@cse.unsw.edu.au