Hide one of the type params of a multi-param typeclass in a function signature

Using TypeFamilies, you could rewrite C into a single-parameter class as follows:

class B (BOf a) => C a where
  type BOf a :: *
  getB :: a -> (T, BOf a)

Which gives you the better looking constraint for f:

f :: C a => a -> c

There is (sadly) no way to omit parameters of a multi-parameter class to obtain a similar result.


If you turn on RankNTypes you can make a type alias that lets you elide b like this:

type C' a t = forall b. C a b => t
f :: C' a (a -> c)
f = g . getB

You can even include further contexts, if necessary, inside the second argument:

f' :: C' a ((Num a, Ord c) => a -> c)
f' = g . getB

This is pretty non-standard, though. You'll want to leave an explanatory comment... and the effort of writing it might be bigger, in the end, than the effort of just including a b at each use of C.