1
votes

Is there a way to have the compiler derive the functionality that I would write manually as:

instance Class c => Class (Trans c) where
    foo1 = lift foo1
    foo2 = lift foo2
    ...
    foo999 = lift foo999
    bar1 = \a b c -> lift $ bar1 a b c
    ...
    baz1 = lift . baz1
    ...

i.e. when a type of class Class is being wrapped in Trans, is it possible to get a free instance of Class for Trans automatically without having to do the heavy lifting :)?

1
I'm not sure I understood what you actually want. That instance will work on all c, so you only have to write it once. I don't think it can be made any shorter, in the general case.chi
But the instance is boring (it just does lifting for all the functions), maybe one could write this concisely (by not having to enumerate all the fooX = lift fooX etc.)jakubdaniel
I see, but any alternative (e.g. Template Haskell) looks worse, unless you really have a large number of class methods.chi
And if you have enough class methods to justify Template Haskell for that, you should consider redesigning your class.dfeuer
I'm not sure I follow this; are you looking for GeneralizedNewtypeDeriving? downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/…Michael

1 Answers

1
votes

If lift is itself a type class function, you can write a general definition for all instances of the type class. Something like:

instance (Class c, Trans t) => Class (t c)

Be careful that this doesn't overlap with any other instances, and is what you want for all these types.

As a more complete example, this code works, even though it's results are sometimes surprising.

{-# LANGUAGE FlexibleInstances #-}

module Inst where

import Control.Applicative (liftA2)

instance (Applicative f, Num n) => Num (f n) where
  (+) = liftA2 (+)
  (*) = liftA2 (*)
  abs = fmap abs
  signum = fmap signum
  fromInteger = pure . fromInteger
  negate = fmap negate