Сопоставление с образцом в синонимах типов / синонимах типов для параметров внутреннего типа

У меня есть что-то похожее на этот класс в моем коде. В моей ситуации нет смысла добавлять a' в качестве еще одного параметра к классу Foo.

class Foo a where
    type FCtx a a' :: Constraint
    type FCtx a a' = ()

    f :: (FCtx a a') => a -> a'

data D b = D b

instance (Integral b) => Foo (D b) where
    -- the next line does not compile because b' does not appear on the LHS
    type FCtx (D b) a' = (a' ~ D b', Integral b') 

    f (D x) = D $ fromIntegral x

Для этого конкретного экземпляра Foo я хочу, чтобы a' был связан таким образом. Единственный способ, который я придумал, чтобы заставить эту работу работать, - это добавить «фиктивный» класс с синонимом «очевидного» типа:

class DClass d where
   type DType d

instance DClass (D b) where
    type DType (D b) = b

Экземпляр Foo теперь становится:

instance (Integral b) => Foo (D b) where
    type FCtx (D b) a' = (a' ~ D (DType a'), Integral (DType a'))
    f (D x) = D $ fromIntegral x

Проблема в том, что мне пришлось создать целый класс (и экземпляр) для моего конкретного типа данных только для того, чтобы выразить синоним/функциональную зависимость типа, которую (D b) определяет b. У меня не будет других экземпляров этого класса, потому что я всегда хочу, чтобы DType a' означало параметр типа для D b.

Вместо этого я хотел бы сделать что-то вроде:

type DParam (D b) = b

instance (Integral b) => Foo (D b) where
     type FCtx (D b) a' = (a' ~ D (DParam a'), Integral (DParam a'))
     f (D x) = D $ fromIntegral x

или, может быть, даже какой-то более приятный способ выразить это ограничение без использования синонимов типов вообще. Кажется глупым, что я должен быть вынужден создать (открытый) класс с синонимом типа с одним экземпляром только для этого, и небезопасно, что другие потенциально могут создать новые экземпляры, которые я не планировал.

По крайней мере, не будет ли какой-то канонический способ превратить «синоним типа, соответствующего шаблону», в класс/экземпляр DClass выше?


person crockeea    schedule 24.01.2013    source источник
comment
Вы всегда можете не экспортировать созданный вами тип класса.   -  person Satvik    schedule 24.01.2013
comment
Это правда. Я просто ищу более легкое решение.   -  person crockeea    schedule 24.01.2013
comment
Если я правильно помню, классы типов экспортируются независимо от того, находятся они в списке экспорта или нет.   -  person vivian    schedule 24.01.2013
comment
Я проверил это, и класс не входит в область действия других файлов для меня, если я не экспортирую его явно.   -  person crockeea    schedule 24.01.2013
comment
@vivian: Возможно, вы думаете об экземплярах, которые всегда экспортируются/импортируются. Классы типов (и все остальное, что имеет собственное имя) можно исключить.   -  person C. A. McCann    schedule 24.01.2013


Ответы (1)


Немного меньший вес, используя семейства типов:

type family DParam d :: *
type instance DParam (D b) = b

Не уверен, что вы можете сделать лучше прямо сейчас...

person Nathan Howell    schedule 24.01.2013