Monad for Const?

Viewed 1231

Why is there no monad instance for Control.Applicative.Const? Is following definition correct, or violates it the monad laws?

instance Monoid a => Monad (Const a) where
  return _ = Const mempty
  (Const x) >>= _ = Const x

And can you think of any useful application?

2 Answers

ehird's answer explains what's wrong with the instance in the question. Here's a more in-depth explanation as to why there can be no other instance that works either, even if you were to choose constraints other than Monoid, unless the type has exactly one inhabitant (e.g., ()). Any given type either has zero inhabitants, one inhabitant, or at least two inhabitants.

Case 1: zero inhabitants

You could write this total function, an obvious contradiction:

{-# LANGUAGE EmptyCase #-}
oops :: void
oops = case getConst (return () :: Const TheEmptyType ()) of {}
Case 2: one inhabitant

This special case actually is possible: it's isomorphic to Proxy. For completeness, here it is:

instance Monad (Const ()) where
    return _ = Const ()
    Const () >>= _ = Const ()
Case 3: at least two inhabitants

Let x and y be two different inhabitants of your chosen type. Write this helper function:

f False = Const x
f True = Const y

Now consider these two instantiations of the left identity law:

return False >>= f = f False
return True >>= f = f True

By parametricity, there's no way to implement return such that return False and return True are different, so you end up with the same value having to equal both Const x and Const y, which is a contradiction since we said earlier that x and y were different.

Related