haskellmonadsdependent-typecontinuationscategory-theory

Can one simplify the Codensity monad on Maybe?


The codensity monad on a type constructor f is defined by:

 newtype C f a = C { unC ∷ forall r. (a → f r) → f r }

It is well known that C f is a monad for any type constructor f (not necessarily covariant). The codensity monad is useful in several ways but it is a complicated type that contains a higher-order function under a universal type quantifier.

My question is, for what f can one show that C f is equivalent to a simpler monad that is defined without type quantifiers?

Some examples where a simplification is possible:

In the first four of those cases, the type equivalence can be derived from the Yoneda identity: forall r. (a -> r) -> F r = F a when F is a covariant functor. The last case is derived via the Church encoding of the inductive type List.

I looked at some other examples and found that in most cases C f does not seem to be equivalent to anything simpler.

Even if we just take f a = Maybe a the resulting type does not seem to be equivalent to a simpler type expression:

 newtype CMaybe a = CMaybe { unCMaybe ∷ forall r. (a → Maybe r) → Maybe r }

The Yoneda identity cannot be used here. My best guess (I have no proof so far) is that CMaybe a = (a -> Bool) -> Bool with some additional laws imposed on the functions of that type. Imposing equations on values can be adequately expressed only within a dependently-typed language.

Can one simplify the codensity monad on Maybe?

Are there other examples of type constructors f where C f can be simplified to a type without type quantifiers?


Solution

  • As mentioned in the comments, a function C Maybe a returns a bit more information than a boolean because the r it returns identifies a single input in the callback, so f k chooses an x such that k x is Just.

    Simplifying the callback type from a -> Maybe r to a -> Bool, we obtain the following dependent function type, written in Agda and in Coq respectively for reference:

    -- Agda
    
    (∀ {r} → (a → Maybe r) → Maybe r)
    ≡
    ((k : a → Bool) → Maybe (∃[ x ] k x ≡ true))
    
    (* Coq *)
    
    (forall r, (a -> option r) -> option r)
    =
    (forall (k : a -> bool), option { x : a | k x = true })
    

    Proof of equivalence in Agda: https://gist.github.com/Lysxia/79846cce777f0394a6f69d84576a325b

    This proves the equivalence of ∀ {r} → (a → Maybe r) → Maybe r and a type without a quantifier: ((f : a → Bool) → Maybe (∃[ x ] f x ≡ true)), which is equivalent to q:: (a → Bool) → Maybe a with the restriction that q(p) equals Just x only if p(x) = true.


    Note that if a is finite, then C Maybe a is also finite. One approach to the problem then is to compute the corresponding cardinality function.