Add ad-hoc warnings to GHC telling the user about the following:[[BR]]
Instance of Monad without instances of Functor/Applicative[[BR]]
Instance of MonadPlus without instance of Alternative[[BR]]
Module defines functions named (<*>), pure or join
Refactoring code to remove these warnings makes sure the AMP will not break the module in the future. Since they are basically meta-deprecations, I would suggest treating them similar to ordinary deprecations.
This is part of phase 1 of the Applicative/Monad proposal (AMP), as discussed on the mailing lists [1]; a more detailed description of the AMP is available on the Wiki [2].
I'm having trouble finding a good middle ground between the global and
local environments in the typechecker. I would like to get an
environment of things that are defined in the current module, but
TcGblEnv includes everything in scope, which is too general.
TcLclEnv is (if I'm right) meant to handle scoping, which is too narrow.
The reason for this is that the AMP warnings should be restricted to a
single module. In the current implementation, having a module import an
AMP-violating module issues a warning from each module using the
offender (including that module itself). It does the job, but it's not
pretty.
Thanks for the helpful hint, Simon. Just before I found that tcg_insts is a good place to look at by successively printing everything in the global environment, and you confirmed that that promising field is indeed correct. Now I can stop worrying about whether I'm coding everything based on a false premise :-)
As some sort of status report, I think the core functionality of issuing the Applicative/Monad warnings is done now (and therefore also Alternative/MonadPlus). What's still missing is making this dependent on compiler flags, printing proper line numbers, and of course the "warn on custom join/<*>/pure" issue. (I should also credit danr for implementing the most significant parts up to this point.)
We're now seeing this warning in containers, but the obvious fix (hide join from the Prelude) does silence it! I expect this module to not generate a warning:
Let me clarify what my concern here is: there are two ways to future proof your code against the upcoming export of join et al in 7.10:
Rename your local join function.
Hide the import from the Prelude (this is what the example above does).
Both will work when 7.10 comes around.
The problem is that the warning is overly trigger-happy; it warns if you go for option 2. Since people like to have warning free code, this means that in practice you have to go with the first option. There might be a good reason to have a function called join in your module, just like there might be a good reason to have a function called map (or any other Prelude name).
I think the warning should be fixed such that it only happens if the code would actually break in 7.10.
I am so curious that I want to ask for the case "You have an instance of Monad, but not Applicative"
why cann't we add default implementation to Applicative typeclass?
class Functor f => Applicative f where pure :: a -> f a default pure :: Monad f => a -> f a pure = return (<*>) :: f (a -> b) -> f a -> f b default (<*>) :: Monad f => f (a -> b) -> f a -> f b (<*>) f a = ap
This patch implements a warning when definitions conflict with the
Applicative-Monad Proposal (AMP), described in #8004 (closed). Namely, this will
cause a warning iff:
You have an instance of Monad, but not Applicative
You have an instance of MonadPlus, but not Alternative
You locally defined a function named join, <*>, or pure.
In GHC 7.10, these warnings will actually be enforced with superclass
constraints through changes in base, so programs will fail to compile
then.
This warning is enabled by default. Unfortunately, not all of
our upstream libraries have accepted the appropriate patches. So we
temporarily fix ./validate by ignoring the AMP warning.
Dan Rosén made an initial implementation of this change, and the
remaining work was finished off by David Luposchainsky. I finally made
some minor refactorings.
I am so curious that I want to ask for the case "You have an instance of Monad, but not Applicative"
why cann't we add default implementation to Applicative typeclass?
class Functor f => Applicative f wherepure :: a -> f adefault pure :: Monad f => a -> f apure = return
At least in the case of pure and return we have the default definition of return in terms of pure. That flow the 'right' way through the class hierarchy and doesn't require an extension. Doing both that and this yields a cycle with no way to detect it through MINIMAL pragmas and the like, which can't straddle two classes.
(<*>) :: f (a -> b) -> f a -> f bdefault (<*>) :: Monad f => f (a -> b) -> f a -> f b(<*>) f a = ap
This one could be done. It'd require a willingness to have an attempt to implement Applicative that doesn't supply a (<*>) to be a compile error rather than a warning, however. (A state that can arise as you write incrementally.) It is a fairly minor concern, but given the difficulty of pushing through Prelude related changes one that may be a sufficient blocker.