Ответ 1
Как я понимаю, ghci
выбирает имена в том же порядке, что и типы. Он использует схему именования, как вы упомянули, для определения имени типа результата, который является [b]
, потому что это имя типа, указанное в определении map
. Затем он решает, что функция, которая является первым параметром map
, должна также возвращать что-то типа b
.
Остальная переменная типа, которая должна быть названа, является, таким образом, переменной типа для второго элемента в кортеле аргументов в fst
, и, опять же, он определяет определение fst
, чтобы решить, какое имя использовать. Определение fst :: (a, b) -> a
, поэтому b
будет предпочтительным именем здесь, но поскольку b
уже занято, он добавляет 1
, чтобы он стал b1
.
Я думаю, что эта система имеет преимущества в ситуациях, когда вы не имеете дело с произвольными типами, как это имеет место здесь. Если результирующий тип выглядит примерно так, например:
castAdd :: (Num n, Num n1, Num n2) => n -> n1 -> n2
... это, возможно, более читаемо, чем:
castAdd :: (Num a, Num b, Num c) => a -> b -> c
... потому что вы можете в основном полагаться на то, что n#
означает числовой тип, поскольку определение класса для Num
равно class Num n where ...
.
EDIT: Да, я знаю, что castAdd
невозможно реализовать, но это просто пример типа.