[commit: ghc] ghc-8.0: ApplicativeDo: allow "return $ e" (10b69f6)
git at git.haskell.org
git at git.haskell.org
Mon Jul 25 18:37:05 UTC 2016
Repository : ssh://git@git.haskell.org/ghc
On branch : ghc-8.0
Link : http://ghc.haskell.org/trac/ghc/changeset/10b69f6871bb243a1fd0259edfd74538839044f9/ghc
>---------------------------------------------------------------
commit 10b69f6871bb243a1fd0259edfd74538839044f9
Author: Simon Marlow <marlowsd at gmail.com>
Date: Sat Jun 18 14:51:04 2016 +0100
ApplicativeDo: allow "return $ e"
Summary:
There's a precedent for special-casing $, as we already have special
typing rules for it.
Test Plan: validate; new test cases
Reviewers: ezyang, austin, niteria, bgamari, simonpj, erikd
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D2345
GHC Trac Issues: #11835
(cherry picked from commit 0ba34b6bac988228948c65ae11d9e08afe82c878)
>---------------------------------------------------------------
10b69f6871bb243a1fd0259edfd74538839044f9
compiler/rename/RnExpr.hs | 22 +++++++++++++---------
docs/users_guide/glasgow_exts.rst | 4 ++++
testsuite/tests/ado/ado004.hs | 12 ++++++++++++
testsuite/tests/ado/ado004.stderr | 6 ++++++
4 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/compiler/rename/RnExpr.hs b/compiler/rename/RnExpr.hs
index 1ca677a..5d97332 100644
--- a/compiler/rename/RnExpr.hs
+++ b/compiler/rename/RnExpr.hs
@@ -1779,19 +1779,23 @@ needJoin [L loc (LastStmt e _ t)]
| Just arg <- isReturnApp e = (False, [L loc (LastStmt arg True t)])
needJoin stmts = (True, stmts)
--- | @Just e@, if the expression is @return e@, otherwise @Nothing@
+-- | @Just e@, if the expression is @return e@ or @return $ e@,
+-- otherwise @Nothing@
isReturnApp :: LHsExpr Name -> Maybe (LHsExpr Name)
isReturnApp (L _ (HsPar expr)) = isReturnApp expr
-isReturnApp (L _ (HsApp f arg))
- | is_return f = Just arg
- | otherwise = Nothing
+isReturnApp (L _ e) = case e of
+ OpApp l op _ r | is_return l, is_dollar op -> Just r
+ HsApp f arg | is_return f -> Just arg
+ _otherwise -> Nothing
where
- is_return (L _ (HsPar e)) = is_return e
- is_return (L _ (HsAppType e _)) = is_return e
- is_return (L _ (HsVar (L _ r))) = r == returnMName || r == pureAName
+ is_var f (L _ (HsPar e)) = is_var f e
+ is_var f (L _ (HsAppType e _)) = is_var f e
+ is_var f (L _ (HsVar (L _ r))) = f r
-- TODO: I don't know how to get this right for rebindable syntax
- is_return _ = False
-isReturnApp _ = Nothing
+ is_var _ _ = False
+
+ is_return = is_var (\n -> n == returnMName || n == pureAName)
+ is_dollar = is_var (`hasKey` dollarIdKey)
{-
************************************************************************
diff --git a/docs/users_guide/glasgow_exts.rst b/docs/users_guide/glasgow_exts.rst
index cbecda7..fd4f947 100644
--- a/docs/users_guide/glasgow_exts.rst
+++ b/docs/users_guide/glasgow_exts.rst
@@ -939,6 +939,10 @@ then the expression will only require ``Applicative``. Otherwise, the expression
will require ``Monad``. The block may return a pure expression ``E`` depending
upon the results ``p1...pn`` with either ``return`` or ``pure``.
+Note: the final statement really must be of the form ``return E`` or
+``pure E``, otherwise you get a ``Monad`` constraint. Using ``$`` as
+in ``return $ E`` or ``pure $ E`` is also acceptable.
+
When the statements of a ``do`` expression have dependencies between
them, and ``ApplicativeDo`` cannot infer an ``Applicative`` type, it
uses a heuristic algorithm to try to use ``<*>`` as much as possible.
diff --git a/testsuite/tests/ado/ado004.hs b/testsuite/tests/ado/ado004.hs
index 6ddc839..fa3c723 100644
--- a/testsuite/tests/ado/ado004.hs
+++ b/testsuite/tests/ado/ado004.hs
@@ -9,6 +9,13 @@ test1 f = do
y <- f 4
return (x + y)
+-- The same using $
+test1a :: Applicative f => (Int -> f Int) -> f Int
+test1a f = do
+ x <- f 3
+ y <- f 4
+ return $ x + y
+
-- Test we can also infer the Applicative version of the type
test2 f = do
x <- f 3
@@ -20,6 +27,11 @@ test2a f = do
x <- f 3
return (x + 1)
+-- The same using $
+test2c f = do
+ x <- f 3
+ return $ x + 1
+
-- Test for just one statement
test2b f = do
return (f 3)
diff --git a/testsuite/tests/ado/ado004.stderr b/testsuite/tests/ado/ado004.stderr
index 8f5a816..ec2ebbc 100644
--- a/testsuite/tests/ado/ado004.stderr
+++ b/testsuite/tests/ado/ado004.stderr
@@ -1,6 +1,8 @@
TYPE SIGNATURES
test1 ::
forall (f :: * -> *). Applicative f => (Int -> f Int) -> f Int
+ test1a ::
+ forall (f :: * -> *). Applicative f => (Int -> f Int) -> f Int
test2 ::
forall t b (f :: * -> *).
(Num b, Num t, Applicative f) =>
@@ -11,6 +13,10 @@ TYPE SIGNATURES
(t -> f b) -> f b
test2b ::
forall (m :: * -> *) a t. (Num t, Monad m) => (t -> a) -> m a
+ test2c ::
+ forall t b (f :: * -> *).
+ (Num b, Num t, Functor f) =>
+ (t -> f b) -> f b
test3 ::
forall a t (m :: * -> *) t1.
(Num t1, Monad m) =>
More information about the ghc-commits
mailing list