Difference between revisions of "Case comprehensions"
(Content transferred from "Cases expressions") |
m (More minor formatting changes) |
||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
[[Category:Proposals]] |
[[Category:Proposals]] |
||
+ | <div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote"> |
||
− | + | One could argue that the notation <code><-</code> 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. |
|
− | + | <tt>[http://web.engr.oregonstate.edu/~erwig/papers/PGandTP_Haskell00.pdf Pattern guards and Transformational Patterns], Martin Erwig and Simon Peyton Jones.</tt> |
|
+ | </div> |
||
Reusing just that part of the list-comprehension syntax seems to work for multi-part function definitions: |
Reusing just that part of the list-comprehension syntax seems to work for multi-part function definitions: |
||
Line 89: | Line 91: | ||
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 102: | ||
_ -> (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 111: | ||
(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 128: | ||
_ -> 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 140: | ||
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 156: | ||
-> Nothing |
-> Nothing |
||
</haskell> |
</haskell> |
||
− | or: |
+ | :or: |
− | <haskell> |
+ | :<haskell> |
mb_scrut dc = |
mb_scrut dc = |
||
cases |
cases |
||
Line 154: | Line 164: | ||
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) |
Latest revision as of 02:12, 5 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)