Difference between revisions of "Cases expressions"
Jump to navigation
Jump to search
(Initial proposal) |
(Content transferred to "Case comprehensions") |
||
Line 1: | Line 1: | ||
+ | #REDIRECT [[Case comprehensions]] |
||
− | [[Category:Proposals]] |
||
− | <blockquote>''One could argue that the notation <code><-</code> is misleading, suggesting the idea of <span style="color:gray">drawn from</span> as in a list comprehension. But it is very nice to reuse precisely the list comprehension syntax.''</blockquote> |
||
+ | [[Category:Pages to be removed]] |
||
− | * [http://web.engr.oregonstate.edu/~erwig/papers/PGandTP_Haskell00.pdf Pattern guards and Transformational Patterns], Martin Erwig and Simon Peyton Jones. |
||
− | |||
− | Reusing just that part of the list-comprehension syntax seems to work for multi-part function definitions: |
||
− | <haskell> |
||
− | clunky env var1 var2 | Just val1 <- lookup env var1, |
||
− | Just val2 <- lookup env var2 = val1 + val2 |
||
− | | otherwise = var1 + var2 |
||
− | </haskell> |
||
− | |||
− | but when it's used in case expressions: |
||
− | <haskell> |
||
− | -- ghc-8.6.5/compiler/ghci/RtClosureInspect.hs, lines 1099-1107 |
||
− | check2 (_, rtti_ty) (_, old_ty) |
||
− | | Just (_, rttis) <- tcSplitTyConApp_maybe rtti_ty |
||
− | = case () of |
||
− | _ | Just (_,olds) <- tcSplitTyConApp_maybe old_ty |
||
− | -> and$ zipWith check2 (map quantifyType rttis) (map quantifyType olds) |
||
− | _ | Just _ <- splitAppTy_maybe old_ty |
||
− | -> isMonomorphicOnNonPhantomArgs rtti_ty |
||
− | _ -> True |
||
− | | otherwise = True |
||
− | </haskell> |
||
− | |||
− | it looks somewhat out-of-place, unless: |
||
− | <haskell> |
||
− | map f xs = [ x <- xs -> f x ] |
||
− | </haskell> |
||
− | |||
− | is considered a suitable replacement for: |
||
− | <haskell> |
||
− | map f xs = [ f x | x <- xs ] |
||
− | </haskell> |
||
− | |||
− | |||
− | Could the GHC example benefit from some more list-comprehension syntax? Let's borrow a new reserved word: |
||
− | <haskell> |
||
− | check2 (_, rtti_ty) (_, old_ty) |
||
− | | Just (_, rttis) <- tcSplitTyConApp_maybe rtti_ty |
||
− | = cases |
||
− | and $ zipWith check2 (map quantifyType rttis) (map quantifyType olds) | |
||
− | Just (_,olds) <- tcSplitTyConApp_maybe old_ty |
||
− | isMonomorphicOnNonPhantomArgs rtti_ty | |
||
− | Just _ <- splitAppTy_maybe old_ty |
||
− | True | otherwise |
||
− | | otherwise = True |
||
− | </haskell> |
||
− | |||
− | ...well, at least the ''unit-case'' workaround is gone. With a little refactoring: |
||
− | <haskell> |
||
− | check2 (_, rtti_ty) (_, old_ty) |
||
− | | Just (_, rttis) <- tcSplitTyConApp_maybe rtti_ty |
||
− | = case () of |
||
− | _ | Just (_,olds) <- tcSplitTyConApp_maybe old_ty |
||
− | -> and $ zipWith qcheck2 rttis olds |
||
− | _ | Just _ <- splitAppTy_maybe old_ty |
||
− | -> isMonomorphicOnNonPhantomArgs rtti_ty |
||
− | _ -> True |
||
− | | otherwise = True |
||
− | |||
− | qcheck2 rtti old = check2 (quantifyType rtti) (quantifyType old) |
||
− | </haskell> |
||
− | |||
− | and the alternate syntax: |
||
− | <haskell> |
||
− | check2 (_, rtti_ty) (_, old_ty) |
||
− | | Just (_, rttis) <- tcSplitTyConApp_maybe rtti_ty |
||
− | = cases |
||
− | and $ zipWith qcheck2 rttis olds | Just (_,olds) <- tcSplitTyConApp_maybe old_ty |
||
− | isMonomorphicOnNonPhantomArgs rtti_ty | Just _ <- splitAppTy_maybe old_ty |
||
− | True | otherwise |
||
− | | otherwise = True |
||
− | |||
− | qcheck2 rtti old = check2 (quantifyType rtti) (quantifyType old) |
||
− | </haskell> |
||
− | |||
− | this particular example is further improved, unless: |
||
− | <haskell> |
||
− | filter p xs = [ x <- xs, p x -> x ] |
||
− | </haskell> |
||
− | |||
− | is considered a reasonable substitute for: |
||
− | <haskell> |
||
− | filter p xs = [ x | x <- xs, p x ] |
||
− | </haskell> |
||
− | |||
− | |||
− | Still not convinced? Here's some other examples: |
||
− | <haskell> |
||
− | -- ghc-8.6.5/compiler/codeGen/StgCmmMonad.hs, lines 819-827 |
||
− | let |
||
− | (test, then_, else_, likely') = case likely of |
||
− | Just False | Just e' <- maybeInvertCmmExpr e |
||
− | -> (e', fbranch, tbranch, Just True) |
||
− | _ -> (e, tbranch, fbranch, likely) |
||
− | </haskell> |
||
− | or: |
||
− | <haskell> |
||
− | let |
||
− | (test, then_, else_, likely') = |
||
− | cases |
||
− | (e', fbranch, tbranch, Just True) | Just False <- likely, |
||
− | Just e' <- maybeInvertCmmExpr e |
||
− | (e, tbranch, fbranch, likely) | otherwise |
||
− | </haskell> |
||
− | |||
− | |||
− | |||
− | <haskell> |
||
− | -- ghc-8.6.5/compiler/basicTypes/Demand.hs, lines 927-934 |
||
− | splitProdDmd_maybe (JD { sd = s, ud = u }) |
||
− | = case (s,u) of |
||
− | (Str _ (SProd sx), Use _ u) | Just ux <- splitUseProdDmd (length sx) u |
||
− | -> Just (mkJointDmds sx ux) |
||
− | (Str _ s, Use _ (UProd ux)) | Just sx <- splitStrProdDmd (length ux) s |
||
− | -> Just (mkJointDmds sx ux) |
||
− | (Lazy, Use _ (UProd ux)) -> Just (mkJointDmds (replicate (length ux) Lazy) ux) |
||
− | _ -> Nothing |
||
− | </haskell> |
||
− | or: |
||
− | <haskell> |
||
− | splitProdDmd_maybe (JD { sd = s, ud = u }) |
||
− | = cases |
||
− | Just (mkJointDmds sx ux) | Str _ (SProd sx) <- s, Use _ u <- u, |
||
− | Just ux <- splitUseProdDmd (length sx) u |
||
− | Just (mkJointDmds sx ux) | Use _ (UProd ux) <- u, Str _ s <- s, |
||
− | Just sx <- splitStrProdDmd (length ux) s |
||
− | Just (mkJointDmds (replicate (length ux) Lazy) ux) | |
||
− | Use _ (UProd ux) <- u, Lazy <- s |
||
− | Nothing | otherwise |
||
− | </haskell> |
||
− | (note the reordering of matches against <code>s</code> and <code>u</code>.) |
||
− | |||
− | |||
− | |||
− | <haskell> |
||
− | -- ghc-8.6.5/compiler/specialise/SpecConstr.hs, lines 2209-2215 |
||
− | mb_scrut dc = case arg_occ of |
||
− | ScrutOcc bs | Just occs <- lookupUFM bs dc |
||
− | -> Just (occs) |
||
− | _other | sc_force env || sc_keen env |
||
− | -> Just (repeat UnkOcc) |
||
− | | otherwise |
||
− | -> Nothing |
||
− | </haskell> |
||
− | or: |
||
− | <haskell> |
||
− | mb_scrut dc = |
||
− | cases |
||
− | Just (occs) | ScrutOcc bs <- arg_occ, Just occs <- lookupUFM bs dc |
||
− | Just (repeat UnkOcc) | sc_force env || sc_keen env |
||
− | Nothing | otherwise |
||
− | </haskell> |
||
− | |||
− | |||
− | One more example: |
||
− | <haskell> |
||
− | concatMap f xs = [ x <- xs, y <- f x -> y ] |
||
− | </haskell> |
||
− | or: |
||
− | <haskell> |
||
− | concatMap f xs = [ y | x <- xs, y <- f x ] |
||
− | </haskell> |
||
− | |||
− | [[User:Atravers|Atravers]] 01:37, 10 July 2020 (UTC) |
Latest revision as of 02:34, 4 August 2021
Redirect to: