Тип (в) равенств при наличии семейств данных
У меня есть семейство типов, которое определяет, находится ли что-то во главе списка типов.
type family AtHead x xs where
AtHead x (x ': xs) = True
AtHead y (x ': xs) = False
Я хочу построить singleton представителя этого результата. Это отлично подходит для списков простых типов.
data Booly b where
Truey :: Booly True
Falsey :: Booly False
test1 :: Booly (AtHead Char [Char, Int])
test1 = Truey
test2 :: Booly (AtHead Int [Char, Int])
test2 = Falsey
Но то, что я действительно хочу сделать, это построить это значение для списка членов индексированного data family
. (На практике я пытаюсь проецировать элементы из гетерогенного списка ID
на основе их типа.)
data family ID a
data User = User
newtype instance ID User = UserId Int
Это работает, когда ID
, который мы ищем, находится во главе списка.
test3 :: Booly (AtHead (ID User) [ID User, Char])
test3 = Truey
Но это не так.
test4 :: Booly (AtHead (ID User) [Int, ID User])
test4 = Falsey
Couldn't match type ‘AtHead (ID User) '[Int, ID User]’
with ‘'False’
Expected type: Booly (AtHead (ID User) '[Int, ID User])
Actual type: Booly 'False
In the expression: Falsey
In an equation for ‘test4’: test4 = Falsey
AtHead (ID User) '[Int, ID User]
не объединяется с 'False
. Похоже, что GHC неохотно принимает решение о том, что ID User
и Int
неравны, хотя ID
является инъективным data family
(и поэтому в принципе равен только (вещи, которые сводятся к) ID User
).
Моя интуиция в отношении того, что решатель ограничений будет и не примет, довольно слаба: я чувствую, что это должно компилироваться. Может ли кто-нибудь объяснить, почему мой код не проверяет тип? Существует ли способ уговорить GHC принять его, возможно, доказав теорему?
Ответы
Ответ 1
Оказывается, это была известная ошибка GHC. Исправление уже находится в головке GHC и должно быть в следующих предстоящих выпусках (GHC 8.0.1 и, возможно, 7.10.3).
Кроме того, наиболее предпочтительным вариантом является предложение @luqui обертки newtype.