Re: Reducing the need for CPP (was: Monad of no `return` Proposal (MRP): Moving `return` out of `Monad`)

It might be enough to just add a NOWARN <warning type> pragma that acts on
a single line/expression. I've seen it in both C++ and Python linters and
it works reasonably well and it's quite general.
On Tue, Oct 6, 2015 at 10:44 AM, Ben Gamari
Sven Panne
writes: 2015-10-05 17:09 GMT+02:00 Gershom B
: On October 5, 2015 at 10:59:35 AM, Bryan O'Sullivan (bos@serpentine.com ) wrote: [...] As for libraries, it has been pointed out, I believe, that without CPP one can write instances compatible with AMP, and also with AMP + MRP. One can also write code, sans CPP, compatible with pre- and post- AMP. [...]
Nope, at least not if you care about -Wall: If you take e.g. (<$>) which is now part of the Prelude, you can't simply import some compatibility module, because GHC might tell you (rightfully) that that import is redundant, because (<$>) is already visible through the Prelude. So you'll have to use CPP to avoid that import on base >= 4.8, be it from it Data.Functor, Control.Applicative or some compat-* module. And you'll have to use CPP in each and every module using <$> then, unless I miss something obvious. AFAICT all transitioning guides ignore -Wall and friends...
This is a fair point that comes up fairly often. The fact that CPP is required to silence redundant import warnings is quite unfortunate. Others languages have better stories in this area. One example is Rust, which has a quite flexible `#[allow(...)]` pragma which can be used to acknowledge and silence a wide variety of warnings and lints [1].
I can think of a few ways (some better than others) how we might introduce a similar idea for import redundancy checks in Haskell,
1. Attach a `{-# ALLOW redundant_import #-}` pragma to a definition,
-- in Control.Applicative {-# ALLOW redundant_import (<$>) #-} (<$>) :: (a -> b) -> f a -> f b (<$>) = fmap
asking the compiler to pretend that any import of the symbol did not exist when looking for redundant imports. This would allow library authors to appropriately mark definitions when they are moved, saving downstream users from having to make any change whatsoever.
2. Or alternatively we could make this a idea a bit more precise,
-- in Control.Applicative {-# ALLOW redundant_import Prelude.(<$>) #-} (<$>) :: (a -> b) -> f a -> f b (<$>) = fmap
Which would ignore imports of `Control.Applicative.(<$>)` only if `Prelude.(<$>)` were also in scope.
3. Attach a `{-# ALLOW redundancy_import #-}` pragma to an import,
import {-# ALLOW redundant_import #-} Control.Applicative
-- or perhaps import Control.Applicative {-# ALLOW redundant_import Control.Applicative #-}
allowing the user to explicitly state that they are aware that this import may be redundant.
4. Attach a `{-# ALLOW redundancy_import #-}` pragma to a name in an import list,
import Control.Applicative ((<$>) {-# ALLOW redundant_import #-})
allowing the user to explicitly state that they are aware that this imported function may be redundant.
In general I'd like to reiterate that many of the comments in this thread describe genuine sharp edges in our language which have presented a real cost in developer time during the AMP and and FTP transitions. I think it is worth thinking of ways to soften these edges; we may be surprised how easy it is to fix some of them.
- Ben
[1] https://doc.rust-lang.org/stable/reference.html#lint-check-attributes
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

On 10/06/2015 11:11 AM, Johan Tibell wrote:
It might be enough to just add a NOWARN <warning type> pragma that acts on a single line/expression. I've seen it in both C++ and Python linters and it works reasonably well and it's quite general.
+1. Simple is good and can hopefully also be backported to older GHC releases. (Provided someone's willing to do said releases, obviously.)
participants (2)
-
Bardur Arantsson
-
Johan Tibell