Можно ли ввести дополнительные переменные типа в суперкласс-ограничение?
При работе с типами семейств часто бывает полезно использовать ограничения равенства, чтобы избежать необходимости повторять некоторое имя функции типа в сигнатуре:
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