написание функций в haskell, которые работают только с ассоциированными типами

I Я пытаюсь найти более элегантный способ написать следующий код.

class C c where
    type E c :: * -> *

class C c => A c where
    g :: E c a -> E c a

class (C c, A c) => D c where
    f :: E c a -> E c a

instance A c => D c where
    f = g

Это вызывает ошибку.

Test.hs:58:9:
    Could not deduce (E c0 ~ E c)
    from the context (A c)
      bound by the instance declaration at Test.hs:57:10-19
    NB: `E' is a type function, and may not be injective
    Expected type: E c a
      Actual type: E c0 a
    Expected type: E c a -> E c a
      Actual type: E c0 a -> E c0 a
    In the expression: g
    In an equation for `f': f = g
Failed, modules loaded: none.

Мое текущее решение - добавить фиктивную переменную, из которой можно получить , какой конкретный C используется.

class C c where
    type E c :: * -> *

class C c => A c where
    g_inner :: c -> E c a -> E c a
g = g_inner undefined

class (C c, A c) => D c where
    f_inner :: c -> E c a -> E c a
f = f_inner undefined

instance A c => D c where
    f_inner = g_inner

Я знаю, что это еще один случай, когда связанные типы не являются инъективными, , но я не могу понять это. Конечно, E может не быть инъективным, но где-то кажется, что информация о том, что g будет работать с конкретным (E c), указанным в классе D ] был утерян.

Мы будем очень благодарны за любое объяснение и, что более важно, лучшие обходные пути. Спасибо!

редактировать

Хорошо, я вижу, что переключение типа на данные заставляет код работать.

Я пытаюсь понять, как это может сработать. Каждый c создает новый тип данных E c . В контексте экземпляра мы должны сопоставить для всех a. ((E) c) a -> ((E) c) a с для всех a. ((E) c) a -> ((E) c) a . Обозначая F = E c , мы затем сопоставляем для всех a. F a -> F a с самим собой.

Мне трудно увидеть, где что-то ломается из-за регистра синонимов типов (связанных типов). Конечно, можно определить два экземпляра A , оба из которых имеют сигнатуру (E c) a -> (E c) a . Но почему было бы неправильно использовать определение из экземпляра A c , который входит в область действия?

Спасибо !!

12
задан gatoatigrado 13 January 2012 в 22:11
поделиться