[GHC] #11128: New `-fwarn-noncanonical-monad-instances` warning

GHC ghc-devs at haskell.org
Tue Nov 24 12:19:52 UTC 2015


#11128: New `-fwarn-noncanonical-monad-instances` warning
-------------------------------------+-------------------------------------
        Reporter:  hvr               |                Owner:  hvr
            Type:  feature request   |               Status:  patch
        Priority:  normal            |            Milestone:  8.0.1
       Component:  Compiler          |              Version:  7.10.2
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):  Phab:D1516
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Description changed by hvr:

Old description:

> When declaring `Applicative` and `Monad` instances, there's a degree of
> freedom in which way to define `return`,`pure`,`(>>)`,`(*>)`. For
> instance, defining
>
> {{{#!hs
> instance Applicative T1 where
>   pure = return
>   (<*>) = ap
>
> instance Monad T1 where
>   return = ...
>   (>>=)  = ...
>   (>>)   = ...
> }}}
>
> is ok, but it's 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.
>
> 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.

New description:

 When declaring `Applicative` and `Monad` instances, there's a degree of
 freedom in which way to define `return`,`pure`,`(>>)`,`(*>)`. For
 instance, defining

 {{{#!hs
 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:

 {{{#!hs
 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.

--

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11128#comment:6>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list