
On 01/10/2021 07:29, Viktor Dukhovni wrote:
More realistic examples:
https://github.com/kazu-yamamoto/dns/blob/master/internal/Network/DNS/Decode...
Or code to process a possibly not yet complete (to be continued) SMTP greeting:
smtpGreeting :: Int -> SmtpReply -> SmtpM B.ByteString smtpGreeting _ r | replyCont r = pure B.empty | code <- replyCode r , code `div` 100 /= 2 = B.empty <$ modify' bail code | otherwise = smtpSendHello where bail code s = s { smtpErr = ProtoErr code $ replyText r }
[...]
-- Viktor.
Perhaps redundantly, this particular instance of a pattern guard can, in my opinion, be written slightly less suggestively with a 'let' pattern guard (not sure if that's the right name): [...] | let code = replyCode r , code `div` 100 /= 2 = B.empty <$ modify' bail code [...] Non-'let' pattern guards, in my experience, are most useful in two cases: 1. You want to do some additional pattern matching on a non-boolean value after having arrived in an interesting case in a larger pattern-match. For example, in the request URL parsing code in my pastebin-haskell: (Some cases and additional code elided) parseRequest :: Method -> ByteString -> Maybe WhatRequest parseRequest method path = let comps = BS.split (fromIntegral (ord '/')) (trimSlashes path) in case (method, comps) of (GET, []) -> Just GetIndex (GET, [x]) | canBeKey x -> Just (ReadPaste x) -- [...] (GET, ["paste", x]) | canBeKey x -> Just (ReadPasteOld x) (GET, ["highlight.pack.css"]) -> Just HighlightCSS (GET, [x]) | Just (path', mime) <- List.lookup x staticFiles -> Just (StaticFile mime path') (POST, ["paste"]) -> Just StorePaste _ -> Nothing Original code here: https://github.com/tomsmeding/pastebin-haskell/blob/25de4aa531a782ca8c34b409... 2. Actually a special case of (1.): this is particularly useful with GADTs and "discovered" type evidence, like in https://github.com/AccelerateHS/accelerate/blob/1ab75f1eb01a1b427563808057d4... . In general, these pattern guards seem to me the Haskell version of Agda's with-patterns [1], which also allow pattern matching on an _additional_ value after the first pattern match has already found a branch. - Tom [1]: https://agda.readthedocs.io/en/v2.5.2/language/with-abstraction.html