Section: 4 Case Expressions and Pattern Matching

第 4 节 Case 表达式与模式匹配

Now for details of pattern matching. We use [Int] instead of [a] since the only value of type [a] is [].

现在来讲模式匹配的细节。我们用 [Int] 而不是 [a],因为类型为 [a] 的

唯一值是 []。

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.

contrived 只是把它的输入与一个大型常量做比较。

Linearity in pattern matching implies that patterns can only compare values with constants. The following is not valid Haskell:

模式匹配中的线性性(linearity)意味着模式只能拿值和常量比较。下面

不是合法的 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

第 4.1 节 模式匹配的语义

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:

最后一个守卫条件常常是 True,用来兜住所有其他情况。标识符

otherwise 被定义为 True,专供守卫条件使用:

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.

守卫条件可以引用模式匹配绑定的任何变量。当没有任何守卫条件为真时,

模式匹配从下一条方程继续。守卫条件也可以引用配套的 where 声明中绑定的值。

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

第 4.2 节 一个示例

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") []