New `-fwarn-noncanonical-monad-instances` warning
When declaring Applicative
and Monad
instances, there's a degree of freedom in which way to define return
,pure
,(>>)
,(*>)
. For instance, defining
instance Applicative T1 where
pure = return
(<*>) = ap
instance Monad T1 where
return = ...
(>>=) = ...
(>>) = {- optimised impl -}
is ok, but this leaves (*>)
with a possibly less optimised version than (>>)
. This can cause performance regressions when generalising code from Monad
to Applicative
.
Moreover, starting with base-4.8
, the return
method gained a default implementation return = pure
which follows the preferred or "canonical" direction of having implementations flow from superclasses to their subclasses.
A proper "canonical" definition of T1
is consequently:
instance Applicative T1 where
pure = ...
(<*>) = ap
(*>) = {- optimised impl -}
instance Monad T1 where
return = pure -- can be left off since base-4.8
(>>=) = ...
(>>) = (*>) -- NB: default impl of (>>) /= (*>)
So this warning is a "lint"-style check to help detect Monad
instances where the definitions of return
/(>>)
are not canonical, i.e. don't match return = pure
and (>>) = (*>)
respectively.