Search code examples
haskelltypeclass

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


Say I have a multi-param typeclass:

class B b => C a b | a -> b where
    getB :: a -> (T, b)

Then I want a function:

f :: C a b => a -> c
f = g . getB

Which uses another function g :: B b => (T, b) -> c and getB, so an instance C a b is needed.

(Disclaimer: the real problem is much more complicated, the above-mentioned is only a simplified version.)

The problem is, given the functional dependency C a b | a -> b, we know that b can be completely decided by a, so theoretically I should be possible not to mention b in the type of f (since it is not used elsewhere but in instance C a b), but I didn't find any way to achieve this.

Also note that due to the existence of constraint B b in class C, I think I cannot use a TypeFamilies extension instead, for the syntax of that leaves nowhere for the type constraint B b to live.

So is there any way that I can hide the implementation details (the irrelevant type parameter b) from the user of this function f?


Solution

  • 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.