Hier folgt die Zusammenfassung der zweiten Hälfte des dritten Kapitels von "Real World Haskell".
Parameterized Types
- introduce type variables into a type declaration
1 2 | data Maybe a = Just a
| Nothing
|
- a is a type variable (like Java generics)
- Maybe is a polymorphic/generic type
- Maybe's with different type variables are distinct types: Maybe Int != Maybe Bool
Recursive Types
- type which is defined in terms of itself
1 2 | data List a = Cons a ( List a)
| Nil
|
- Nil: simples value of type List, may be used as parameter for Cons
1 2 3 | data Tree a = Node a (Tree a) (Tree a)
| Empty
deriving (Show)
|
- binary tree is either a node with two children or an empty value
- children are themselves binary trees
Reporting Errors
- standard function: error :: String -> a
- can be called if something went wrong
1 2 3 4 | mySecond :: [a] - > a
mySecond xs = if null (tail xs)
then error “ list too short”
else head (tail xs)
|
1 2 | : type error
error :: [Char] - > a
|
- return type a just to possibly call it anywhere
- actually it does not return a value like normal functions
- instead it immediately aborts evaluation
Weakness
- caller can’t distinguish between recoverable and error (no try/catch blocks possible)
- error will always terminates evaluation
- alternative: use Maybe to represent the possibility of an error
Reporting Errors with Maybe
1 2 3 4 5 | safeSecond :: [a] - > Maybe a
safeSecond [] = Nothing
safeSecond xs = if null (tail xs)
then Nothing
else Just (head (tail xs))
|
- caller can decide what to do with nullable
1 2 3 | tidySecond :: [a] - > Maybe a
tidySecond (_:x:_) = Just x
tidySecond _ = Nothing
|
Local Variables
1 2 3 4 5 | lend amount balance = let reserve = 100
newBalance = balance - amount
in if balance < reserve
then Nothing
else Just newBalance
|
- local variables with let within body of a function
- “in” ends block of variable declaration
Shadowing
- nest multiple “let” blocks
1 2 3 | foo = let a = 1
in let b = 2
in a + b
|
- repeated variable names in nested let blocks are legal
1 2 | bar = let x = 1
in ((let x = “foo” in x), x)
|
- inner x ([Char]) is hiding outer x (Int)
- Be careful! shadowing a function parameter is also allowed (enable compiler warnings!)
Local variables in where clause
1 2 3 4 5 | lend2 amount balance = if amount < reserve * 0.5
then Just newBalance
else Nothing
where reserve = 100
newBalance = balance - amount
|
Local Functions
1 2 3 4 5 | pluralise :: String - > [ Int ] - > [String]
pluralise word counts = map plural counts
where plural 0 = “no “ + + word + + “s”
plural 1 = “one “ + + word
plural n = show n + + “ “ + + word + + “s”
|
Global variables
Indentation
Guards