6.10.2.1. Ограничения равенства
Контекст типа может включать ограничения равенства вида t1 ~ t2, которые обозначают, что типы t1 и t2 должны быть одинаковыми. При наличии семейств типов, определить, равны ли два типа, как правило, нельзя локально. Поэтому контексты сигнатур функций могут включать ограничения равенства, как в следующем примере:
sumCollects :: (Collects c1, Collects c2, Elem c1 ~ Elem c2) => c1 -> c2 -> c2
где требуется, чтобы тип элемента c1 и c2 были одинаковыми. В общем случае, типы t1 и t2 ограничения равенства могут быть произвольными монотипами; то есть, они могут не содержать никаких квантификаторов, независимо от того, включены ли типы высшего порядка.
Ограничения равенства также могут появляться в контекстах классов и экземпляров. Первые позволяют просто перевести программы, использующие функциональные зависимости, в программы, использующие синонимы семейств вместо. Общая идея заключается в переписывании объявления класса вида
class C a b | a -> b
в
class (F a ~ b) => C a b where type F a
То есть, мы представляем каждую функциональную зависимость (FD) a1 .. an -> b семейством типов FD F a1 .. an и равенством контекста суперклассов F a1 .. an ~ b, по существу присваивая имя функциональной зависимости. В экземплярах классов мы определяем типы экземпляров семейств FD в соответствии с заголовком класса. Сигнатуры методов не затрагиваются этим процессом.
6.10.2.2. Неоднородное равенство
GHC также поддерживает разнородное равенство, которое связывает два типа потенциально разных порядков. Неоднородное равенство записывается как ~~. Вот порядки ~ и ~~, чтобы лучше понять их различие:
(~) :: forall k. k -> k -> Constraint (~~) :: forall k1 k2. k1 -> k2 -> Constraint
Пользователи, скорее всего, захотят ~, но ~~ доступно, если GHC не может априори определить, что два рассматриваемых типа имеют одинаковый порядок. Доказательство, что (a :: k1) ~~ (b :: k2) сообщает GHC, что k1 и k2 одинаковы и что a и b одинаковы.
Поскольку ~ является более распространённым отношением равенства, GHC выводит ~~ как ~ , если не установлен -fprint-equality-relations.
6.10.2.3. Неподнятое неоднородное равенство
Внутри GHC существует ещё одно отношение равенства (~#). Оно неоднородно (как ~~) и используется только внутри. Оно может появиться в сообщениях об ошибках и других выводах только при включении -fprint-equality-relations.
6.10.2.4. Ограничение Coercible
Ограничение Coercible t1 t2 аналогично t1 ~ t2, но обозначает репрезентативное равенство между t1 и t2 в смысле ролей (Ролей). Оно экспортируется модулем Data.Coerce, который также содержит документацию. Более подробные сведения и обсуждение можно найти в статье “Безопасные преобразования”.