Скрыть один из параметров типа класса типов с несколькими параметрами в сигнатуре функции - PullRequest
0 голосов
/ 23 января 2019

Допустим, у меня есть класс типов с несколькими параметрами:

class B b => C a b | a -> b where
    getB :: a -> (T, b)

Тогда я хочу функцию:

f :: C a b => a -> c
f = g . getB

, которая использует другую функцию g :: B b => (T, b) -> c и getB, поэтому необходим экземпляр C a b.

(Отказ от ответственности: реальная проблема гораздо сложнее, вышеупомянутая является лишь упрощенной версией.)

Проблема в том, что с учетом функциональной зависимости C a b | a -> b мы знаем, что b может быть полностью решен a, поэтому теоретически я должен иметь возможность не упоминать b в типе f ( поскольку он используется не в другом месте, а в экземпляре C a b), но я не нашел способа достичь этого.

Также обратите внимание, что из-за существования ограничения B b в классе C, я думаю, что я не могу вместо этого использовать расширение TypeFamilies, так как синтаксис этого не оставляет ничего для ограничения типа B b для жизни.

Так есть ли способ скрыть детали реализации (нерелевантный параметр типа b) от пользователя этой функции f?

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Если вы включите RankNTypes, вы можете создать псевдоним типа, который позволит вам получить b, например:

type C' a t = forall b. C a b => t
f :: C' a (a -> c)
f = g . getB

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

f' :: C' a ((Num a, Ord c) => a -> c)
f' = g . getB

Хотя это довольно нестандартно. Вы захотите оставить пояснительный комментарий ... и, в конце концов, усилия по его написанию могут быть больше, чем просто добавление b при каждом использовании C.

0 голосов
/ 23 января 2019

Используя TypeFamilies, вы можете переписать C в класс с одним параметром следующим образом:

class B (BOf a) => C a where
  type BOf a :: *
  getB :: a -> (T, BOf a)

Что дает вам более привлекательное ограничение для f:

f :: C a => a -> c

Нет (к сожалению) способа пропустить параметры многопараметрического класса для получения аналогичного результата.

...