Базовый вопрос о мономорфизме / полиморфизме Хаскелла (HList) - PullRequest
4 голосов
/ 05 марта 2011

Я Хаскель и нуб из Stackoverflow, и вот мой первый и, вероятно, довольно простой вопрос Хаскеля.

module M where

import Data.HList

data R r a 

r1 = undefined :: R a Int
r2 = undefined :: R a Double

rPair :: R r a -> R r b -> (R r a, R r b)
rPair = (,)

rp = rPair r1 r2

Это имеет смысл, даже если r1 и r2 полиморфны в r rPair выравнивает тип r в соответствии с типом подпись. Есть ли технический термин для этого «выравнивания»?

class HList l => RList r l
instance RList r HNil
instance RList r l => RList r (HCons (R r a) l)

rCons :: RList r l => R r a -> l -> (HCons (R r a) l)
rCons = hCons

rc = rCons r1 (rCons r2 hNil)

rCons прекрасно работает, если переданные R мономорфны в r, ограничивая тип r списка по желанию. но если они полиморфны в r, это не выравнивает их так, как rPair делает, и дает ошибку (определение rc выше).

No instance for (RList r (HCons (R r1 Double) HNil))

У меня есть смутная интуиция относительно того, почему это так, но мой вопрос состоит из двух частей. Может ли кто-нибудь четко объяснить феномен? Как бы я написал rCons так, чтобы следующее будет иметь место?

r1 = undefined :: R a Int
r2 = undefined :: R a Double

rc :: HCons (R a Int) (HCons (R a Double) HNil)
rc = rCons r1 (rCons r2 hNil)

Спасибо, _c

1 Ответ

1 голос
/ 05 марта 2011

Чтобы ответить на ваш второй вопрос, вы можете использовать ограничение эквивалентности типов (из расширения TypeFamilies), чтобы ослабить определение RList экземпляра:

class HList l => RList r l
instance RList r HNil
instance (RList r1 l, r1 ~ r2) => RList r1 (HCons (R r2 a) l)

Теперь ваш rc будет выведен на требуемый тип.

Я не думаю, что могу «ясно объяснить» явление, хотя (кто-то наверняка это сделает), но очевидно, что разница между rPair и rCons заключается в том, что тогда как первый связывает rтип обоих аргументов для одной и той же переменной типа, последний не делает: второй аргумент просто l ограничен тем, что должен быть некоторый экземпляр RList для этого l).Поскольку для rc нет сигнатуры типа (обратите внимание, что если вы предоставите один из ваших исходных примеров проверок типов) и r1 и r2 имеют полиморфизм, не эквивалентно , r, компилятор пытается найтиОпределение экземпляра для RList r (HCons (R r1 Double) HNil) (r происходит из 1-го аргумента и r1 - из 2-го) и не может это сделать.С помощью ограничения эквивалентности типов мы определяем экземпляр RList с двумя различными r1 и r2 с единственным условием, что они должны быть эквивалентными, поэтому похоже, что GHC связывает их с одной и той же полиморфной переменной типа при разрешении экземпляра RList за l.

...