[Haskell-cafe] Improving MPTC usability when fundeps aren't appropriate?

Bertram Felgenhauer bertram.felgenhauer at googlemail.com
Thu Aug 13 18:32:05 EDT 2009


Daniel Peebles wrote:
> I've been playing with multiparameter typeclasses recently and have
> written a few "uncallable methods" in the process. For example, in
> 
> class Moo a b where
>   moo :: a -> a
> 
> Another solution would be to artificially force moo to take
> a "dummy" b so that the compiler can figure out which instance you
> meant. That's what I've been doing in the mean time, but wouldn't it
> be simpler and less hackish to add a some form of "instance
> annotation", like a type annotation, that would make it possible to
> specify what instance you wanted when it's ambiguous?

Syntax aside, dummy arguments have a disadvantage when it comes to
optimizing code, because the compiler doesn't know that the dummy
argument is unused in the function; indeed you could define instances
where the dummy argument is used.

For this reason it's technically better to use a newtype instead:

    newtype Lambda t a = Lambda { unLambda :: a }

and, say,

    class Moo a b where
        moo :: Lambda b (a -> a)

Note that we can convert between functions taking dummy arguments and
such "lambda" types easily:

    lambdaToDummy :: Lambda t a -> t -> a
    lambdaToDummy a _ = unLambda a

    dummyToLambda :: (t -> a) -> Lambda t a
    dummyToLambda f = Lambda (f undefined)

In fact, lambdaToDummy makes a great infix operator:

    (@@) :: Lambda t a -> t -> a
    (@@) = lambdaToDummy

    infixl 1 @@

Now we can write

    moo @@ (undefined :: x)

where with dummy arguments we would write

    moo (undefined :: x) .

The compiler will inline (@@) and lambdaToDummy (they're both small)
and produce

   unLambda moo ,

that is, the plain value of type a -> a that we wanted to use in the
first place. All this happens after type checking and fixing the
instance of Moo to use.

Bertram


More information about the Haskell-Cafe mailing list