Как GHCi выбирает имена для переменных типа? - PullRequest
11 голосов
/ 15 декабря 2011

При использовании интерактивного интерпретатора GHC можно запросить предполагаемый тип выражения:

Prelude> :t map
map :: (a -> b) -> [a] -> [b]

Кажется, что он берет имена переменных типа из сигнатуры, поскольку map определено как

map :: (a -> b) -> [a] -> [b]
map _ []     = []
map f (x:xs) = f x : map f xs

в прелюдии.Это имеет большой смысл!Мой вопрос: как выбираются имена переменных типа, когда не дана подпись?

Примером может быть

Prelude> :t map fst
map fst :: [(b, b1)] -> [b]

, где выбираются имена b и b1.Ясно, что переименование должно иметь место, но простое начало с a, b, ... вместо этого дало бы

map fst :: [(a, b)] -> [a]

, что, на мой взгляд, немного более читабельно.

1 Ответ

13 голосов
/ 15 декабря 2011

Насколько я понимаю, 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 ....

РЕДАКТИРОВАТЬ: Да, я знаю, что castAdd невозможно реализовать, но это всего лишь пример типа.

...