Можно ли ввести дополнительные переменные типа в суперкласс-ограничение?

При работе с типами семейств часто бывает полезно использовать ограничения равенства, чтобы избежать необходимости повторять некоторое имя функции типа в сигнатуре:

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

Это работает, даже если аббревиатура не появляется в самой подписи, только в ограничениях.

С классами это, по-видимому, невозможно,

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

жалуется, что переменная типа b не входит в область видимости.

Является ли какой-то способ достичь подобной вещи, чтобы избежать небольшого количества повторений-шаблонов?

Ответы

Ответ 1

Это удивило меня, узнав, что вы не можете этого сделать (я использовал ту же технику и знаю, что она работает в объявлениях экземпляров), но, похоже, существует давняя GHC для поддержки этого.

Возможно, вы можете использовать ConstraintKinds, чтобы получить такую ​​же выгоду:

{-# 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