Gentle Introduction to Haskell 98, Online Supplement Part 10 Covers Sections 4, 4.1, 4.2 > module Part10() where > import Prelude hiding (take,(^)) Section: 4 Case Expressions and Pattern Matching Now for details of pattern matching. We use [Int] instead of [a] since the only value of type [a] is []. > contrived :: ([Int], Char, (Int, Float), String, Bool) -> Bool > contrived ([], 'b', (1, 2.0), "hi", True) = False > contrived x = True -- add a second equation to avoid runtime errors > e1 :: Bool > e1 = contrived ([], 'b', (1, 2.0), "hi", True) > e2 :: Bool > e2 = contrived ([1], 'b', (1, 2.0), "hi", True) Contrived just tests its input against a big constant. Linearity in pattern matching implies that patterns can only compare values with constants. The following is not valid Haskell: member x [] = False member x (x:ys) = True -- Invalid since x appears twice member x (y:ys) = member x ys > f :: [a] -> [a] > f s@(x:xs) = x:s > f _ = [] > e3 = f "abc" Another use of _: > middle :: (a,b,c) -> b > middle (_,x,_) = x > e4 :: Char > e4 = middle (True, 'a', "123") > (^) :: Int -> Int -> Int > x ^ 0 = 1 > x ^ (n+1) = x*(x^n) > e5 :: Int > e5 = 3^3 > e6 :: Int > e6 = 4^(-2) -- Notice the behavior of the + pattern on this one Section: 4.1 Pattern Matching Semantics Here's an extended example to illustrate the left -> right, top -> bottom semantics of pattern matching. > foo :: (Int,[Int],Int) -> Int > foo (1,[2],3) = 1 > foo (2,(3:_),3) = 2 > foo (1,_,3) = 3 > foo _ = 4 > e7 = foo (1,[],3) > e8 = foo (1,error "in e8",3) > e9 = foo (1,1:(error "in e9"),3) > e10 = foo (2,error "in e10",2) > e11 = foo (3,error "in e11 (second)",error "in e11 (third)") Now add some guards: > sign :: Int -> Int > sign x | x > 0 = 1 > | x == 0 = 0 > | x < 0 = -1 > e12 = sign 3 The last guard is often `True' to catch all other cases. The identifier `otherwise' is defined as True for use in guards: > max' :: Int -> Int -> Int > max' x y | x > y = x > | otherwise = y Guards can refer to any variables bound by pattern matching. When no guard is true, pattern matching resumes at the next equation. Guards may also refer to values bound in an associated where declaration. > inOrder :: [Int] -> Bool > inOrder (x1:x2:xs) | x1 <= x2 = True > inOrder _ = False > e13 = inOrder [1,2,3] > e14 = inOrder [2,1] Section: 4.2 An Example > take :: Int -> [a] -> [a] > take 0 _ = [] > take _ [] = [] > take (n+1) (x:xs) = x:take n xs > take' :: Int -> [a] -> [a] > take' _ [] = [] > take' 0 _ = [] > take' (n+1) (x:xs) = x:take' n xs > e15, e16, e17, e18 :: [Int] > e15 = take 0 (error "e15") > e16 = take' 0 (error "e16") > e17 = take (error "e17") [] > e18 = take' (error "e18") [] Continued in part11.lhs