Single [[Functions|Functions]] [[Defining/Pattern Matching|implementations]] may have 1 or more guard clauses. > [!info] > [[case .. of]] expressions can also use guard clauses. These allow functions to switch on boolean expressions based on the inputs, and can often take up less space than explicit [[Expressions/if .. then .. else ..]] expressions. Guard patterns are placed after the function arguments and take the form `| = `. There can be any number of guard patterns, as long as all cases are exhaustively covered. ### Example Strings can't be structurally pattern matched, so in order to ask if a string starts with a substring we need to call a function like `Data.String.Utils.startsWith`. We could do this with `if then else`: ```haskell ensureLeadingSlash :: String -> String ensureLeadingSlash str = if String.Util.startsWith "/" then str else "/" <> str ``` Alternatively, we could implement this with guard patterns: ```haskell ensureLeadingSlash :: String -> String ensureLeadingSlash str | String.Util.startsWith "/" str = str | otherwise = "/" <> str ``` When the first pattern `String.Util.startsWith "/" str` returns `true`, the function will use `... = str`. Otherwise, it will prepend `/` to `str`. > [!tip] > `otherwise` is simply an alias for `true`, specifically for better-reading fallthrough guard patterns. Much less often, but occasionally useful is the ability to structurally pattern match in a guard clause: ```haskell ensureLeadingSlashM :: Maybe String -> String ensureLeadingSlashM mstr | Just s <- mstr, String.Util.startsWith "/" s = s | otherwise = "" ``` Here the bit `Just s <- mstr` is saying "when `mstr` is `Just s`..." then `String.Util.startsWith "/" s` says "and `s` starts with `"/"`..." `| Just s <- mstr, startsWith "/" s = s` "when `mstr` is `Just s` and `s` starts with `"/"`, return s" `| otherwise = ""` otherwise return `""` You can have any number of comma-separated guard bindings before the last boolean expression.