Motivation
Sebastian Rettig
“Recursion is important to Haskell because unlike imperative languages, you do computations in Haskell by declaring what something is instead of declaring how you get it.” ([1])
“Recursion is important to Haskell because unlike imperative languages, you do computations in Haskell by declaring what something is instead of declaring how you get it.” ([1])
Functional Programming
● No Variables● Functions only, eventually stored in
Modules– Behavior do not change, once defined
– → Function called with same parameter calculates always the same result
● Function definitions (Match Cases)● Recursion (Memory)
Haskell Features
● Pure Functional Programming Language● Lazy Evaluation ● Pattern Matching and Guards● List Comprehension● Type Polymorphism
When you start...
● You want to do big projects with Haskell?
● Then start simple, because:
– a function is Simple and...
Simple Simple Simple Simple
Simple Simple
Simple Simple
Simple
SimpleAbstraction- Level
BIGProject
Let's start simple● You need a Framework to start with Haskell?
– then write one, if you really think you need one :)
– but be aware of● Haskell == simple● Framework == should also be simple
● a simple function:
– just ignore the function header at the beginning
countNum 1 = “One”
countNum 2 = “Two”
countNum x = “toooo difficult to count...”
How to implement the Factorial?
● Remember:
“Recursion is important to Haskell because unlike imperative languages, you do computations in Haskell by declaring what something is instead of declaring how you get it.” ([1])
● Okay, then look at the definition:
– Imperative definition
– Recursive definition
Let's look at the imperative way...
● Imperative
function factorial(n) { int result = 1; if (n == 0) return result; } for (int i=1; i<n; i++) { result *= i; } return result;}
● Recursive
…and translate to the functional way
● Imperative
function fact(n) { int result = 1; if (n == 0) return result; } for (int i=1; i<n; i++) { result *= i; } return result;}
● Recursive
fact 0 = 1fact n = n * fact (n-1)
● and in comparison with the definition:
● BUT imperative also possible:
fact' 0 = 1fact' n = product [1..n]
● compared with the definition:
The maximum value of a List?
● Remember:
“Recursion is important to Haskell because unlike imperative languages, you do computations in Haskell by declaring what something is instead of declaring how you get it.” ([1])
● Okay, then look at the definition:
Let's look at the imperative way...
● Imperative
function max(array list) { if (empty(list)) { throw new Exception(); } max = list[0] for (int i=0; i<length(list);
i++) { if (list[i] > max) { max = list[i]; } } return max;}
● Recursive
…and translate to the functional way ● Imperative
function max(array list) { if (empty(list)) { throw new Exception(); } max = list[0] for (int i=0; i<length(list);
i++) { if (list[i] > max) { max = list[i]; } } return max;}
● Recursive
maxList [] = error “empty”maxList [x] = xmaxList (x:xs) | x > maxTail = x | otherwise = maxTail where maxTail = maxList xs
● or simpler:maxList [] = error “empty”maxList [x] = xmaxList (x:xs) = max x (maxList xs)
● and in comparison with the definition:
Types in Haskell (1)
Starts with uppercase first character
● Int bounded from -2147483648 to 2147483647
● Integer unbounded (for big numbers) but slower than Int
● Float floating point (single precision)
● Double floating point (double precision)
● Bool boolean
● Char character
● String list of Char (String == [Char])
Types in Haskell (2)
● Lists: must be homogenous (entries from the same type)
– [] empty List
– [Int] List of Int
– But e.g. [Int, Bool] not allowed (not homogenous)!
● Tuples: can contain different types BUT have fixed length
– () empty tuple (has only 1 value)
– (Int, Bool) tuple of a pair Int, Bool
– (Int, Bool, Bool) tuple of Int, Bool, Bool
List-Functions● head returns first element of list
– head [1,2,3] returns 1
● tail returns list without first element
– tail [1,2,3] returns [2,3]
● init returns list without last element
– init [1,2,3] returns [1,2]
● last returns last element of list
– last [1,2,3] returns 3
Tuple-Functions● fst returns first element of a pair
fst (1, “one”) returns 1
– only usable on Tuples of Pairs!!!
fst (1,”one”,True) throws Exception!!!
● snd returns second element of a pair
snd (1, “one”) returns “one”
– only usable on Tuples of Pairs!!!– snd (1,”one”,True) throws Exception!!!
● zip creates a list of tuples from two lists
– zip [1,2,3] [“one”,“two”,”three”] returns [(1,“one”),(2,”two”),(3,”three”)]
Type Polymorphism (1)
● Statically typed, but Compiler can read type from context (type inference)
● → no need to set type explicitly
● → makes function more generic for different kinds of types (type polymorphism)
– Why should I use quicksort :: [Int] -> [Int]– even if I also want to sort character?Hugs> quicksort ['f','a','d','b']
"abdf"
Type Polymorphism (2)
● the header of our previous implementations could befact :: Int -> Int
maxList :: [Int] -> Int
● but is only limited to Int, but maxList could also handle Char
● → why not make it generic?maxList :: [a] -> a
● but what happens, if the corresponding Type is not comparable or cannot be ordered?
Type Polymorphism (3)
● Solution: use TypeclassesmaxList :: (Ord a) => [a] -> a
● then we can be sure to use (<,<=, ==, /=, >=, >)
● function header can contain multiple typeclassesmaxList :: (Ord a, Eq b) => [a] -> [b] -> a
● In Haskell-Interpreter: to list the function header
:t <function_name>
Typeclasses (1)
● define properties of the types
● like an interface
● Typeclasses:
– Eq can be compared
– Ord can be ordered (>, <, >=, <=) (extending Eq)
– Show can be shown as string
– Read opposite of Show
– Enum sequentially ordered types (can be enumerated
and usable in List-Ranges ['a'..'e'])
Typeclasses (2)
● Typeclasses:
– Bounded upper/lower bound (minBound, maxBound)
– Num types behave like numbers (must already be Show, Eq)
– Integral contains only integrals (subclass of Num)
– Floating corresponding real numbers (subclass of Num)
● if all Types of tuple are in same Typeclass → Tuple also in Typeclass
Lazy Evaluation
● What happens, if I do this? (Yes it makes no sense, but just for demonstration)
max a b
| a > b = a
| otherwise = b
where temp = cycle “LOL ”
Sources
[1] Haskell-Tutorial: Learn you a Haskell (http://learnyouahaskell.com/, 2012/03/15)
[2] The Hugs User-Manual (http://cvs.haskell.org/Hugs/pages/hugsman/index.html, 2012/03/15)
[3] The Haskellwiki (http://www.haskell.org/haskellwiki, 2012/03/15)