Skip to content

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.

Edited by Herbert Valerio Riedel
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information