Commit 5cfc2680 authored by giorgidze's avatar giorgidze Committed by Simon Peyton Jones

Removing the default grouping clause from the SQL-like comprehension notation ;

parent b4d08f19
......@@ -943,12 +943,8 @@ data StmtLR idL idR
deriving (Data, Typeable)
data TransForm -- The 'f' below is the 'using' function, 'e' is the by function
= ThenForm -- then f or then f by e (depending on trS_by)
| GroupFormU -- group using f or group using f by e (depending on trS_by)
| GroupFormB -- group by e
-- In the GroupByFormB, trS_using is filled in with
-- 'groupWith' (list comprehensions) or
-- 'groupM' (monad comprehensions)
= ThenForm -- then f or then f by e (depending on trS_by)
| GroupForm -- then group using f or then group by e using f (depending on trS_by)
deriving (Data, Typeable)
\end{code}
......@@ -1078,12 +1074,7 @@ expressions:
=>
guard exp >> [ body | stmts ]
Grouping/parallel statements require the 'Control.Monad.Group.groupM' and
'Control.Monad.Zip.mzip' functions:
[ body | stmts, then group by e, rest]
=>
groupM [ body | stmts ] >>= \bndrs -> [ body | rest ]
Parallel statements require the 'Control.Monad.Zip.mzip' function:
[ body | stmts1 | stmts2 | .. ]
=>
......@@ -1126,9 +1117,7 @@ pprTransStmt :: OutputableBndr id => Maybe (LHsExpr id)
-> SDoc
pprTransStmt by using ThenForm
= sep [ ptext (sLit "then"), nest 2 (ppr using), nest 2 (pprBy by)]
pprTransStmt by _ GroupFormB
= sep [ ptext (sLit "then group"), nest 2 (pprBy by) ]
pprTransStmt by using GroupFormU
pprTransStmt by using GroupForm
= sep [ ptext (sLit "then group"), nest 2 (pprBy by), nest 2 (ptext (sLit "using") <+> ppr using)]
pprBy :: OutputableBndr id => Maybe (LHsExpr id) -> SDoc
......
......@@ -51,7 +51,7 @@ module HsUtils(
-- Stmts
mkTransformStmt, mkTransformByStmt, mkExprStmt, mkBindStmt, mkLastStmt,
emptyTransStmt, mkGroupUsingStmt, mkGroupByStmt, mkGroupByUsingStmt,
emptyTransStmt, mkGroupUsingStmt, mkGroupByUsingStmt,
emptyRecStmt, mkRecStmt,
-- Template Haskell
......@@ -243,10 +243,9 @@ mkHsIf c a b = HsIf (Just noSyntaxExpr) c a b
mkNPat lit neg = NPat lit neg noSyntaxExpr
mkNPlusKPat id lit = NPlusKPat id lit noSyntaxExpr noSyntaxExpr
mkTransformStmt :: [LStmt idL] -> LHsExpr idR -> StmtLR idL idR
mkTransformByStmt :: [LStmt idL] -> LHsExpr idR -> LHsExpr idR -> StmtLR idL idR
mkTransformStmt :: [LStmt idL] -> LHsExpr idR -> StmtLR idL idR
mkTransformByStmt :: [LStmt idL] -> LHsExpr idR -> LHsExpr idR -> StmtLR idL idR
mkGroupUsingStmt :: [LStmt idL] -> LHsExpr idR -> StmtLR idL idR
mkGroupByStmt :: [LStmt idL] -> LHsExpr idR -> StmtLR idL idR
mkGroupByUsingStmt :: [LStmt idL] -> LHsExpr idR -> LHsExpr idR -> StmtLR idL idR
emptyTransStmt :: StmtLR idL idR
......@@ -254,12 +253,10 @@ emptyTransStmt = TransStmt { trS_form = undefined, trS_stmts = [], trS_bndrs = [
, trS_by = Nothing, trS_using = noLoc noSyntaxExpr
, trS_ret = noSyntaxExpr, trS_bind = noSyntaxExpr
, trS_fmap = noSyntaxExpr }
mkTransformStmt ss u = emptyTransStmt { trS_form = ThenForm, trS_stmts = ss, trS_using = u }
mkTransformByStmt ss u b = emptyTransStmt { trS_form = ThenForm, trS_stmts = ss, trS_using = u, trS_by = Just b }
mkGroupByStmt ss b = emptyTransStmt { trS_form = GroupFormB, trS_stmts = ss, trS_by = Just b }
mkGroupUsingStmt ss u = emptyTransStmt { trS_form = GroupFormU, trS_stmts = ss, trS_using = u }
mkGroupByUsingStmt ss b u = emptyTransStmt { trS_form = GroupFormU, trS_stmts = ss
, trS_by = Just b, trS_using = u }
mkTransformStmt ss u = emptyTransStmt { trS_form = ThenForm, trS_stmts = ss, trS_using = u }
mkTransformByStmt ss u b = emptyTransStmt { trS_form = ThenForm, trS_stmts = ss, trS_using = u, trS_by = Just b }
mkGroupUsingStmt ss u = emptyTransStmt { trS_form = GroupForm, trS_stmts = ss, trS_using = u }
mkGroupByUsingStmt ss b u = emptyTransStmt { trS_form = GroupForm, trS_stmts = ss, trS_using = u, trS_by = Just b }
mkLastStmt expr = LastStmt expr noSyntaxExpr
mkExprStmt expr = ExprStmt expr noSyntaxExpr noSyntaxExpr placeHolderType
......
......@@ -1584,22 +1584,16 @@ squals :: { Located [LStmt RdrName] } -- In reverse order, because the last
transformqual :: { Located ([LStmt RdrName] -> Stmt RdrName) }
-- Function is applied to a list of stmts *in order*
: 'then' exp { LL $ \leftStmts -> (mkTransformStmt leftStmts $2) }
-- >>>
| 'then' exp 'by' exp { LL $ \leftStmts -> (mkTransformByStmt leftStmts $2 $4) }
| 'then' 'group' 'by' exp { LL $ \leftStmts -> (mkGroupByStmt leftStmts $4) }
-- <<<
-- These two productions deliberately have a shift-reduce conflict. I have made 'group' into a special_id,
-- which means you can enable TransformListComp while still using Data.List.group. However, this makes the two
-- productions ambiguous. I've set things up so that Happy chooses to resolve the conflict in that case by
-- choosing the "group by" variant, which is what we want.
--
-- This is rather dubious: the user might be confused as to how to parse this statement. However, it is a good
-- practical choice. NB: Data.List.group :: [a] -> [[a]], so using the first production would not even type check
-- if /that/ is the group function we conflict with.
| 'then' 'group' 'using' exp { LL $ \leftStmts -> (mkGroupUsingStmt leftStmts $4) }
: 'then' exp { LL $ \leftStmts -> (mkTransformStmt leftStmts $2) }
| 'then' exp 'by' exp { LL $ \leftStmts -> (mkTransformByStmt leftStmts $2 $4) }
| 'then' 'group' 'using' exp { LL $ \leftStmts -> (mkGroupUsingStmt leftStmts $4) }
| 'then' 'group' 'by' exp 'using' exp { LL $ \leftStmts -> (mkGroupByUsingStmt leftStmts $4 $6) }
-- Note that 'group' is a special_id, which means that you can enable
-- TransformListComp while still using Data.List.group. However, this
-- introduces a shift/reduce conflict. Happy chooses to resolve the conflict
-- in by choosing the "group by" variant, which is what we want.
-----------------------------------------------------------------------------
-- Parallel array expressions
......
......@@ -292,7 +292,6 @@ basicKnownKeyNames
-- Monad comprehensions
, guardMName
, liftMName
, groupMName
, mzipName
]
......@@ -328,7 +327,7 @@ gHC_PRIM, gHC_TYPES, gHC_GENERICS,
gHC_CONC, gHC_IO, gHC_IO_Exception,
gHC_ST, gHC_ARR, gHC_STABLE, gHC_PTR, gHC_ERR, gHC_REAL,
gHC_FLOAT, gHC_TOP_HANDLER, sYSTEM_IO, dYNAMIC, tYPEABLE, tYPEABLE_INTERNAL, gENERICS,
dOTNET, rEAD_PREC, lEX, gHC_INT, gHC_WORD, mONAD, mONAD_FIX, mONAD_GROUP, mONAD_ZIP,
dOTNET, rEAD_PREC, lEX, gHC_INT, gHC_WORD, mONAD, mONAD_FIX, mONAD_ZIP,
aRROW, cONTROL_APPLICATIVE, gHC_DESUGAR, rANDOM, gHC_EXTS,
cONTROL_EXCEPTION_BASE :: Module
......@@ -375,7 +374,6 @@ gHC_INT = mkBaseModule (fsLit "GHC.Int")
gHC_WORD = mkBaseModule (fsLit "GHC.Word")
mONAD = mkBaseModule (fsLit "Control.Monad")
mONAD_FIX = mkBaseModule (fsLit "Control.Monad.Fix")
mONAD_GROUP = mkBaseModule (fsLit "Control.Monad.Group")
mONAD_ZIP = mkBaseModule (fsLit "Control.Monad.Zip")
aRROW = mkBaseModule (fsLit "Control.Arrow")
cONTROL_APPLICATIVE = mkBaseModule (fsLit "Control.Applicative")
......@@ -1007,10 +1005,9 @@ choiceAName = varQual aRROW (fsLit "|||") choiceAIdKey
loopAName = varQual aRROW (fsLit "loop") loopAIdKey
-- Monad comprehensions
guardMName, liftMName, groupMName, mzipName :: Name
guardMName, liftMName, mzipName :: Name
guardMName = varQual mONAD (fsLit "guard") guardMIdKey
liftMName = varQual mONAD (fsLit "liftM") liftMIdKey
groupMName = varQual mONAD_GROUP (fsLit "mgroupWith") groupMIdKey
mzipName = varQual mONAD_ZIP (fsLit "mzip") mzipIdKey
......@@ -1578,11 +1575,10 @@ toIntegerClassOpKey = mkPreludeMiscIdUnique 192
toRationalClassOpKey = mkPreludeMiscIdUnique 193
-- Monad comprehensions
guardMIdKey, liftMIdKey, groupMIdKey, mzipIdKey :: Unique
guardMIdKey, liftMIdKey, mzipIdKey :: Unique
guardMIdKey = mkPreludeMiscIdUnique 194
liftMIdKey = mkPreludeMiscIdUnique 195
groupMIdKey = mkPreludeMiscIdUnique 196
mzipIdKey = mkPreludeMiscIdUnique 197
mzipIdKey = mkPreludeMiscIdUnique 196
---------------- Template Haskell -------------------
......
......@@ -779,13 +779,10 @@ rnStmt ctxt (L loc (ParStmt segs _ _ _)) thing_inside
rnStmt ctxt (L loc (TransStmt { trS_stmts = stmts, trS_by = by, trS_form = form
, trS_using = using })) thing_inside
= do { -- Rename the 'using' expression in the context before the transform is begun
(using', fvs1) <- case form of
GroupFormB -> do { (e,fvs) <- lookupStmtName ctxt groupMName
; return (noLoc e, fvs) }
_ -> rnLExpr using
(using', fvs1) <- rnLExpr using
-- Rename the stmts and the 'by' expression
-- Keep track of the variables mentioned in the 'by' expression
-- Keep track of the variables mentioned in the 'by' expression
; ((stmts', (by', used_bndrs, thing)), fvs2)
<- rnStmts (TransStmtCtxt ctxt) stmts $ \ bndrs ->
do { (by', fvs_by) <- mapMaybeFvRn rnLExpr by
......
......@@ -540,8 +540,6 @@ tcMcStmt _ (ExprStmt rhs then_op guard_op _) res_ty thing_inside
-- Grouping statements
--
-- [ body | stmts, then group by e ]
-- -> e :: t
-- [ body | stmts, then group by e using f ]
-- -> e :: t
-- f :: forall a. (a -> t) -> m a -> m (m a)
......
......@@ -1087,7 +1087,7 @@ employees = [ ("Simon", "MS", 80)
output = [ (the dept, sum salary)
| (name, dept, salary) &lt;- employees
, then group by dept
, then group by dept using groupWith
, then sortWith by (sum salary)
, then take 5 ]
</programlisting>
......@@ -1099,8 +1099,8 @@ In this example, the list <literal>output</literal> would take on
</programlisting>
</para>
<para>There are three new keywords: <literal>group</literal>, <literal>by</literal>, and <literal>using</literal>.
(The function <literal>sortWith</literal> is not a keyword; it is an ordinary
function that is exported by <literal>GHC.Exts</literal>.)</para>
(The functions <literal>sortWith</literal> and <literal>groupWith</literal> are not keywords; they are ordinary
functions that are exported by <literal>GHC.Exts</literal>.)</para>
<para>There are five new forms of comprehension qualifier,
all introduced by the (existing) keyword <literal>then</literal>:
......@@ -1176,21 +1176,6 @@ output = [ (the x, y)
</listitem>
<listitem>
<programlisting>
then group by e
</programlisting>
<para>This form of grouping is essentially the same as the one described above. However,
since no function to use for the grouping has been supplied it will fall back on the
<literal>groupWith</literal> function defined in
<ulink url="&libraryBaseLocation;/GHC-Exts.html"><literal>GHC.Exts</literal></ulink>. This
is the form of the group statement that we made use of in the opening example.</para>
</listitem>
<listitem>
<programlisting>
......@@ -1305,34 +1290,10 @@ do (x,y) &lt;- take 2 (do x &lt;- [1..10]
</para>
<programlisting>
[ x | x &lt;- [1,1,2,2,3], then group by x ]
[ x | x &lt;- [1,1,2,2,3], then group by x using GHC.Exts.groupWith ]
[ x | x &lt;- [1,1,2,2,3], then group using myGroup ]
</programlisting>
<para>
The basic <literal>then group by e</literal> statement is
translated using the <literal>mgroupWith</literal> function, which
requires a <literal>MonadGroup</literal> instance, defined in
<ulink url="&libraryBaseLocation;/Control-Monad-Group.html"><literal>Control.Monad.Group</literal></ulink>:
</para>
<programlisting>
do x &lt;- mgroupWith (do x &lt;- [1,1,2,2,3]
return x)
return x
</programlisting>
<para>
Note that the type of <literal>x</literal> is changed by the
grouping statement.
</para>
<para>
The grouping function can also be defined with the
<literal>using</literal> keyword.
</para>
</listitem>
<listitem>
<para>
......@@ -1390,7 +1351,7 @@ Lists of qualifiers: Q,R,S
-- Basic forms
D[ e | ] = return e
D[ e | p &lt;- e, Q ] = e &gt;&gt;= \p -&gt; D[ e | Q ]
D[ e | p &lt;- e, Q ] = e &gt;&gt;= \p -&gt; D[ e | Q ]
D[ e | e, Q ] = guard e &gt;&gt; \p -&gt; D[ e | Q ]
D[ e | let d, Q ] = let d in D[ e | Q ]
......@@ -1406,8 +1367,6 @@ D[ e | Q then group using f, R ] = f D[ Qv | Q ] &gt;&gt;= \ys -&gt;
case (fmap selQv1 ys, ..., fmap selQvn ys) of
Qv -&gt; D[ e | R ]
D[ e | Q then group by b, R ] = D[ e | Q then group by b using mgroupWith, R ]
D[ e | Q then group by b using f, R ] = f (\Qv -&gt; b) D[ Qv | Q ] &gt;&gt;= \ys -&gt;
case (fmap selQv1 ys, ..., fmap selQvn ys) of
Qv -&gt; D[ e | R ]
......@@ -1422,7 +1381,6 @@ return GHC.Base t1 -&gt; m t2
(&gt;&gt;) GHC.Base m1 t1 -&gt; m2 t2 -&gt; m3 t3
guard Control.Monad t1 -&gt; m t2
fmap GHC.Base forall a b. (a-&gt;b) -&gt; n a -&gt; n b
mgroupWith Control.Monad.Group forall a. (a -&gt; t) -&gt; m1 a -&gt; m2 (n a)
mzip Control.Monad.Zip forall a b. m a -&gt; m b -&gt; m (a,b)
</programlisting>
The comprehension should typecheck when its desugaring would typecheck.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment