Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to introduce additional type variables into a superclass-constraint?

When dealing with type families, it is often handy to use equality constraints to avoid having to repeat some type-function's name in a signature:

class Foo f where
  type BulkyAssociatedType f :: *
  foo :: BulkyAssociatedType f -> f
  ...

bar :: forall m f b .
       ( Monad m, Foo f, b ~ BulkyAssociatedType f
       , Monoid b, Monoid (m b)
       ) => f -> m f

This works even if the abbreviation doesn't turn up in the signature itself, only in the constraints.

With classes, this is apparently not possible;

class ( Foo f, b ~ BulkyAssociatedType f, Monoid b, ...) => Bar f

complains about type variable b not being in scope.

Is the some way to achieve a similar thing, to avoid a bit of repetition-boilerplate?

like image 703
leftaroundabout Avatar asked Jan 21 '14 22:01

leftaroundabout


1 Answers

It surprised me to learn you can't do that (I've used the same technique and know it works in instance declarations), but there seems to be a long-standing GHC feature request to support this.

Maybe you can use ConstraintKinds to get the same benefit:

{-# LANGUAGE TypeFamilies , FlexibleContexts , ConstraintKinds #-}
import Data.Monoid

class Foo f where
  type BulkyAssociatedType f :: *

type B f = (Monoid (BulkyAssociatedType f))

class ( Foo f, B f) => Bar f
like image 151
jberryman Avatar answered Oct 09 '22 11:10

jberryman