TL; DR: порядок переменных типа определяется первым столкновением слева направо.В случае сомнений используйте :type +v
.
Не используйте :type
Использование :type
вводит в заблуждение здесь.:type
выводит тип целого выражения.Поэтому, когда вы пишете :t (,)
, средство проверки типов просматривает
(,) :: forall a b. a -> b -> (a, b)
и создает экземпляры всех файлов с новыми переменными типа
(,) :: a1 -> b1 -> (a1, b1)
, что необходимо, если вы примените (,)
,Увы, вы этого не сделаете, поэтому вывод типа почти сделан, и он обобщает все свободные переменные, и вы получаете, например,
(,) :: forall {b} {a}. a -> b -> (a, b)
Этот шаг не дает никаких гарантий относительно порядка свободной переменной, и компилятор может свободно меняться.
Также обратите внимание, что он пишет forall {a}
вместо forall a
, что означает, что вы не можете использовать приложение видимого типа здесь.
Use :type +v
Но, конечно, вы можете использовать (,) @Bool
- но здесь средство проверки типов обрабатывает первое выражение по-разному и не выполняет этот шаг создания экземпляра / обобщения.
И вы можете получить этоповедение в GHCi также - передача +v
в :type
:
:type +v (,)
(,) :: forall a b. a -> b -> (a, b)
:type +v (,) @Bool
(,) @Bool :: forall b. Bool -> b -> (Bool, b)
Смотрите, нет {…}
вокруг переменных типа!
Где этот порядоквзято из?
В разделе руководства пользователя GHC по приложению видимого типа указано:
Если сигнатура типа идентификатора не содержит явного запроса, типпеременные аргументы отображаются слева направопорядок, в котором переменные появляются в типе.Таким образом, переменные типа foo :: Monad m => ab -> m (ac) будут иметь порядок m, a, b, c.
Это относится только к вещам, которые имеют явныйТип подписи.Не существует гарантированного порядка для переменных в выведенных типах, но вы также не можете использовать выражения с выведенными типами с VisibleTypeApplication
.