Softwerkskammer

 

Kapitel 3 - Zusammenfassung Teil 2

Hier folgt die Zusammenfassung der zweiten Hälfte des dritten Kapitels von "Real World Haskell".

Parameterized Types

  • introduce type variables into a type declaration
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
data List a = Cons a (List a)
              | Nil
  • Nil: simples value of type List, may be used as parameter for Cons
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
mySecond :: [a] -> a
mySecond xs = if null (tail xs)
then error “list too short”
else head (tail xs)
: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

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
tidySecond :: [a] -> Maybe a
tidySecond (_:x:_) = Just x
tidySecond _ = Nothing

Local Variables

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
foo = let a = 1
          in let b = 2
             in a + b
  • repeated variable names in nested let blocks are legal
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

lend2 amount balance = if amount < reserve * 0.5
                       then Just newBalance
                       else Nothing
                       where reserve = 100
                             newBalance = balance - amount
  • better readability

Local Functions

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

itemName = “foobar”

Indentation

Guards