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

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

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
Другие вопросы по тегам