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

Jan-Willem Maessen jmaessen at alum.mit.edu
Tue Oct 6 12:25:34 UTC 2015


On Tue, Oct 6, 2015 at 4:44 AM, Ben Gamari <ben at smart-cactus.org> wrote:

> Sven Panne <svenpanne at gmail.com> writes:
>
> > 2015-10-05 17:09 GMT+02:00 Gershom B <gershomb at gmail.com>:
> >
> >> On October 5, 2015 at 10:59:35 AM, Bryan O'Sullivan (bos at 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.
>

One obvious solution I haven't seen mentioned is the ability to add
nonexistent identifier to a hiding clause (these identifiers might
presumably exist in some other version of the import):

import Prelude hiding ((<$>))

I can see the argument for marking such imports with a pragma, though it
gets a bit ugly.

-Jan-Willem Maessen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20151006/c4319a11/attachment.html>


More information about the Libraries mailing list