Семьи закрытого типа не работают должным образом

Пару часов назад я собрал GHC HEAD, чтобы поэкспериментировать с новыми блестящими семействами закрытых шрифтов.

{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-}

type family C a b where
  C  a [a] = [a]
  C  a  a  = [a]

Теперь я пытаюсь использовать C:

class Combine a b where
  combine :: a -> b -> C a b

instance Combine a [a] where
  combine a b = a : b

instance Combine a a where
  combine a b = [a, b]

Что приводит к этой ошибке:

Couldn't match expected type ‛C a a’ with actual type ‛[a]’
...
In the expression: [a, b]
In an equation for ‛combine’: combine a b = [a, b]
In the instance declaration for ‛Combine a a’

Мне кажется, что второе уравнение отдельно от первого ([a] a не может быть упрощено до a a, каким бы ни было a), так почему оно не компилируется?


person Artyom    schedule 13.10.2013    source источник
comment
Разве вы не имеете в виду, что C a a = a будет C a a = [a] или второй экземпляр будет combine a b = a++b?   -  person MdxBhmt    schedule 14.10.2013
comment
Это несоответствие задумано? C [a] a = [a] но instance Combine a [a]?   -  person Vladimir Matveev    schedule 14.10.2013
comment
Ой. Я скопировал немного неправильный код. Исправлено, но ошибка осталась прежней.   -  person Artyom    schedule 14.10.2013
comment
у меня нет под рукой GHC HEAD, поэтому я не могу проверить себя прямо сейчас, но что произойдет, если вы поместите два предложения в другом порядке?   -  person Philip JF    schedule 14.10.2013
comment
@PhilipJF: Я тоже должен был упомянуть об этом, верно. Когда я меняю уравнения типов, первый экземпляр дает сбой, а второй компилируется.   -  person Artyom    schedule 14.10.2013
comment
Вы уверены, что правильно скопировали и вставили? У меня нет HEAD-версии GHC, но если я сделаю это семейство закрытых типов нормальным, скучным старым семейством открытых типов (и включу гибкие экземпляры и MPTC), эти объявления классов и экземпляров прекрасно компилируются с GHC 7.6.   -  person Daniel Wagner    schedule 14.10.2013
comment
@DanielWagner: Я проверил прямо сейчас — создал новый файл и вставил в него код из моего вопроса (с добавлением гибких экземпляров и MPTC). Да все равно не компилируется.   -  person Artyom    schedule 14.10.2013


Ответы (1)


Я немного просмотрел почтовые архивы. К сожалению, кажется, что a ~ b не исключает возможности того, что a ~ [b], потому что такая ерунда принята:

type family G = [G]

В результате в экземпляре Combine a a, когда мы вызываем C a a, чтобы узнать, каким должен быть возвращаемый тип, никакая редукция невозможна: поскольку мы ничего не знаем о a, мы еще не знаем, выбрать ли C a a или C a [a] ветвь семейства типов C, и мы пока не можем делать редукцию.

Более подробную информацию можно найти в этой ветке списка рассылки, в которой много последующих сообщений (которые, кажется, трудно найти по предыдущей ссылке) в следующем месяце архив по потокам. Вся ситуация на самом деле кажется мне немного странной, хотя я не уверен, что было бы лучшим решением.

person Daniel Wagner    schedule 13.10.2013
comment
Кажется, что возможный обходной путь — изменить второй экземпляр на instance (C a a ~ [a]) => Combine a a where ... (и включить UndecidableInstances). Для реализации a в конкретных типах LHS может быть уменьшен. - person kosmikus; 14.10.2013
comment
(Кроме того, я написал электронное письмо Ричарду Айзенбергу, парню, ответственному за новую функцию семейств закрытых шрифтов, чтобы подтвердить это объяснение, поскольку я не был уверен, что правильно его понял. Он согласен.) - person Daniel Wagner; 15.10.2013