Skip to content

Derive instances for classes with associated types

When trying to derive an instance of a class with associated types

import Data.Distributive
import Data.Functor.Rep

data Pair a = a :# a 
  deriving Functor

instance Distributive Pair where
  distribute :: Functor f => f (Pair a) -> Pair (f a)
  distribute = distributeRep

instance Representable Pair where
  type Rep Pair = Bool

  index :: Pair a -> (Bool -> a)
  index (a :# _) False = a
  index (_ :# b) True  = b

newtype PAIR a = PAIR (Pair a) 
  deriving (Functor, Representable)

instance Distributive PAIR where
  distribute = {- distributeRep -}
    • Can't make a derived instance of ‘Representable PAIR’
        (even with cunning GeneralizedNewtypeDeriving):
        the class has associated types
    • In the newtype declaration for ‘PAIR’

But it could create an instance

instance Representable PAIR where
  type Rep PAIR = Bool

  index :: forall a. PAIR a -> (Bool -> a)
  index = coerce (index :: Pair a -> (Bool -> a))

Same with complicated expressions like

infixr 9 ·
type (·) = Compose

newtype P f g h a = P (Product (f·g·f) (h·f·g) a)
  deriving (Functor, Foldable, Traversable, Applicative, Alternative, Distributive)

instance (Functor       f, Functor       g, Functor       h, 
          Representable f, Representable g, Representable h) 
       => Distributive  (P f g h) where
  distribute = distributeRep

instance (Functor       f, Functor       g, Functor       h, 
          Representable f, Representable g, Representable h) 
       => Representable (P f g h) where
  type Rep (P f g h) = Either (Rep f, (Rep g, Rep f)) (Rep h, (Rep f, Rep g))

  index :: (P f g h) a -> (Either (Rep f, (Rep g, Rep f)) (Rep h, (Rep f, Rep g)) -> a)
  index = coerce (index @(Product (f·g·f) (h·f·g)))

  tabulate :: (Either (Rep f, (Rep g, Rep f)) (Rep h, (Rep f, Rep g)) -> a) -> (P f g h) a
  tabulate = coerce (tabulate @(Product (f·g·f) (h·f·g)))

Is this too limited to work in general

Edited by Icelandjack
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information