Обычно, чтобы ввести проверить
case e of
K1 ... -> e1
K2 ... -> e2
...
требуется, чтобы все выражения ei
имеют общий тип.
Это еще актуально при использовании GADTs, за исключением того, что в каждой отрасли конструктор обеспечивает некоторый тип равенства уравнений T ~ T'
которые известнаят в этой отрасли. Следовательно, при проверке того, что все ei
имеют общий тип, мы больше не требуем, чтобы их типы были идентичными, но только чтобы быть равными, когда сохраняются уравнения типа.
В частности:
f :: T a -> a -> a
f x y = -- we know x :: T a , y :: a
case x of
T0 _ -> -- provides a ~ Bool
True -- has type Bool
T1 -> -- provides a ~ a (useless)
y -- has type a
Здесь нам нужно проверить Bool ~ a
, которое было бы ложным в целом, но здесь становится истинным, потому что нам нужно только проверить это при условии равенства a ~ Bool
. И в таком случае это становится правдой!
(Честно говоря, система типа делает что-то немного другое, проверку вместо этого, если обе ветви равны типа, объявленного в подписи (под их известными равенствами.) - но позвольте мне сохранить его простым для GADT сопоставления с образцом такой подписи всегда требуется в той или иной форме)
Обратите внимание, что это вся суть GADTs. - они позволяют проверять тип соответствия шаблону, ветви которого, по-видимому вовлекают различные типы.
GADTs является особенным в том смысле, что на самом деле может программу проверка получить информацию, когда вы шаблон матч на них. Из-за типа, заданного 'T0', когда совпадение шаблонов успешно выполняется в конструкторе' T0', GHC может быть уверен, что 'a ~ Bool', поэтому код, который вы написали, имеет тип. –