Difference between revisions of "Case comprehensions"
(Content transferred from "Cases expressions") |
m (List of examples reformatted) |
||
Line 89: | Line 89: | ||
Still not convinced? Here's some other examples: |
Still not convinced? Here's some other examples: |
||
+ | |||
⚫ | |||
+ | {| |
||
+ | | |
||
+ | * <haskell> |
||
-- ghc-8.6.5/compiler/codeGen/StgCmmMonad.hs, lines 819-827 |
-- ghc-8.6.5/compiler/codeGen/StgCmmMonad.hs, lines 819-827 |
||
let |
let |
||
Line 97: | Line 100: | ||
_ -> (e, tbranch, fbranch, likely) |
_ -> (e, tbranch, fbranch, likely) |
||
</haskell> |
</haskell> |
||
− | or: |
+ | :or: |
− | <haskell> |
+ | :<haskell> |
let |
let |
||
(test, then_, else_, likely') = |
(test, then_, else_, likely') = |
||
Line 106: | Line 109: | ||
(e, tbranch, fbranch, likely) | otherwise |
(e, tbranch, fbranch, likely) | otherwise |
||
</haskell> |
</haskell> |
||
+ | |} |
||
+ | {| |
||
⚫ | |||
+ | | |
||
+ | * <haskell> |
||
-- ghc-8.6.5/compiler/basicTypes/Demand.hs, lines 927-934 |
-- ghc-8.6.5/compiler/basicTypes/Demand.hs, lines 927-934 |
||
splitProdDmd_maybe (JD { sd = s, ud = u }) |
splitProdDmd_maybe (JD { sd = s, ud = u }) |
||
Line 120: | Line 126: | ||
_ -> Nothing |
_ -> Nothing |
||
</haskell> |
</haskell> |
||
− | or: |
+ | :or: |
− | <haskell> |
+ | :<haskell> |
splitProdDmd_maybe (JD { sd = s, ud = u }) |
splitProdDmd_maybe (JD { sd = s, ud = u }) |
||
= cases |
= cases |
||
Line 132: | Line 138: | ||
Nothing | otherwise |
Nothing | otherwise |
||
</haskell> |
</haskell> |
||
− | (note the reordering of matches against <code>s</code> and <code>u</code>.) |
+ | :(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 |
-- ghc-8.6.5/compiler/specialise/SpecConstr.hs, lines 2209-2215 |
||
mb_scrut dc = case arg_occ of |
mb_scrut dc = case arg_occ of |
||
Line 146: | Line 154: | ||
-> Nothing |
-> Nothing |
||
</haskell> |
</haskell> |
||
− | or: |
+ | :or: |
− | <haskell> |
+ | :<haskell> |
mb_scrut dc = |
mb_scrut dc = |
||
cases |
cases |
||
Line 154: | Line 162: | ||
Nothing | otherwise |
Nothing | otherwise |
||
</haskell> |
</haskell> |
||
+ | |} |
||
+ | {| |
||
− | |||
+ | | |
||
− | One more example: |
+ | * One more example: |
⚫ | |||
⚫ | |||
concatMap f xs = [ x <- xs, y <- f x -> y ] |
concatMap f xs = [ x <- xs, y <- f x -> y ] |
||
</haskell> |
</haskell> |
||
− | or: |
+ | :or: |
− | <haskell> |
+ | :<haskell> |
concatMap f xs = [ y | x <- xs, y <- f x ] |
concatMap f xs = [ y | x <- xs, y <- f x ] |
||
</haskell> |
</haskell> |
||
+ | |} |
||
[[User:Atravers|Atravers]] 01:37, 10 July 2020 (UTC) |
[[User:Atravers|Atravers]] 01:37, 10 July 2020 (UTC) |
Revision as of 02:51, 4 August 2021
One could argue that the notation
<-
is misleading, suggesting the idea of drawn from as in a list comprehension. But it is very nice to reuse precisely the list comprehension syntax.
- 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:
clunky env var1 var2 | Just val1 <- lookup env var1,
Just val2 <- lookup env var2 = val1 + val2
| otherwise = var1 + var2
but when it's used in case expressions:
-- 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
it looks somewhat out-of-place, unless:
map f xs = [ x <- xs -> f x ]
is considered a suitable replacement for:
map f xs = [ f x | x <- xs ]
Could the GHC example benefit from some more list-comprehension syntax? Let's borrow a new reserved word:
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
...well, at least the unit-case workaround is gone. With a little refactoring:
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)
and the alternate syntax:
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)
this particular example is further improved, unless:
filter p xs = [ x <- xs, p x -> x ]
is considered a reasonable substitute for:
filter p xs = [ x | x <- xs, p x ]
Still not convinced? Here's some other examples:
|
|
|
|
Atravers 01:37, 10 July 2020 (UTC)