+
+<Sect1 id="pattern-guards">
+<Title>Pattern guards</Title>
+
+<Para>
+<IndexTerm><Primary>Pattern guards (Glasgow extension)</Primary></IndexTerm>
+The discussion that follows is an abbreviated version of Simon Peyton Jones's original <ULink URL="http://research.microsoft.com/~simonpj/Haskell/guards.html">proposal</ULink>. (Note that the proposal was written before pattern guards were implemented, so refers to them as unimplemented.)
+</Para>
+
+<Para>
+Suppose we have an abstract data type of finite maps, with a
+lookup operation:
+
+<ProgramListing>
+lookup :: FiniteMap -> Int -> Maybe Int
+</ProgramListing>
+
+The lookup returns <Function>Nothing</Function> if the supplied key is not in the domain of the mapping, and <Function>(Just v)</Function> otherwise,
+where <VarName>v</VarName> is the value that the key maps to. Now consider the following definition:
+</Para>
+
+<ProgramListing>
+clunky env var1 var2 | ok1 && ok2 = val1 + val2
+| otherwise = var1 + var2
+where
+ m1 = lookup env var1
+ m2 = lookup env var2
+ ok1 = maybeToBool m1
+ ok2 = maybeToBool m2
+ val1 = expectJust m1
+ val2 = expectJust m2
+</ProgramListing>
+
+<Para>
+The auxiliary functions are
+</Para>
+
+<ProgramListing>
+maybeToBool :: Maybe a -> Bool
+maybeToBool (Just x) = True
+maybeToBool Nothing = False
+
+expectJust :: Maybe a -> a
+expectJust (Just x) = x
+expectJust Nothing = error "Unexpected Nothing"
+</ProgramListing>
+
+<Para>
+What is <Function>clunky</Function> doing? The guard <Literal>ok1 &&
+ok2</Literal> checks that both lookups succeed, using
+<Function>maybeToBool</Function> to convert the <Function>Maybe</Function>
+types to booleans. The (lazily evaluated) <Function>expectJust</Function>
+calls extract the values from the results of the lookups, and binds the
+returned values to <VarName>val1</VarName> and <VarName>val2</VarName>
+respectively. If either lookup fails, then clunky takes the
+<Literal>otherwise</Literal> case and returns the sum of its arguments.
+</Para>
+
+<Para>
+This is certainly legal Haskell, but it is a tremendously verbose and
+un-obvious way to achieve the desired effect. Arguably, a more direct way
+to write clunky would be to use case expressions:
+</Para>
+
+<ProgramListing>
+clunky env var1 var1 = case lookup env var1 of
+ Nothing -> fail
+ Just val1 -> case lookup env var2 of
+ Nothing -> fail
+ Just val2 -> val1 + val2
+where
+ fail = val1 + val2
+</ProgramListing>
+
+<Para>
+This is a bit shorter, but hardly better. Of course, we can rewrite any set
+of pattern-matching, guarded equations as case expressions; that is
+precisely what the compiler does when compiling equations! The reason that
+Haskell provides guarded equations is because they allow us to write down
+the cases we want to consider, one at a time, independently of each other.
+This structure is hidden in the case version. Two of the right-hand sides
+are really the same (<Function>fail</Function>), and the whole expression
+tends to become more and more indented.
+</Para>
+
+<Para>
+Here is how I would write clunky:
+</Para>
+
+<ProgramListing>
+clunky env var1 var1
+ | Just val1 <- lookup env var1
+ , Just val2 <- lookup env var2
+ = val1 + val2
+...other equations for clunky...
+</ProgramListing>
+
+<Para>
+The semantics should be clear enough. The qualifers are matched in order.
+For a <Literal><-</Literal> qualifier, which I call a pattern guard, the
+right hand side is evaluated and matched against the pattern on the left.
+If the match fails then the whole guard fails and the next equation is
+tried. If it succeeds, then the appropriate binding takes place, and the
+next qualifier is matched, in the augmented environment. Unlike list
+comprehensions, however, the type of the expression to the right of the
+<Literal><-</Literal> is the same as the type of the pattern to its
+left. The bindings introduced by pattern guards scope over all the
+remaining guard qualifiers, and over the right hand side of the equation.
+</Para>
+
+<Para>
+Just as with list comprehensions, boolean expressions can be freely mixed
+with among the pattern guards. For example:
+</Para>
+
+<ProgramListing>
+f x | [y] <- x
+ , y > 3
+ , Just z <- h y
+ = ...
+</ProgramListing>
+
+<Para>
+Haskell's current guards therefore emerge as a special case, in which the
+qualifier list has just one element, a boolean expression.
+</Para>
+</Sect1>
+
+