Haskell: тип вывода и функциональный состав
Этот вопрос был вдохновлен этим ответом на другой вопрос, указывая, что вы можете удалить каждое вхождение элемента из списка, используя функцию, определенную как:
removeall = filter . (/=)
Работа с карандашом и бумагой из типов filter
, (/=)
и (.)
, функция имеет тип
removeall :: (Eq a) => a -> [a] -> [a]
что именно вы ожидаете от его контракта. Однако с GHCi 6.6 я получаю
gchi> :t removeall
removeall :: Integer -> [Integer] -> [Integer]
если я не укажу тип явно (в этом случае он отлично работает). Почему Haskell выдает такой конкретный тип для функции?
Ответы
Ответ 1
Почему Haskell выдает такой конкретный тип для функции?
GHCi использует тип defaulting, чтобы вывести более конкретный тип из набора возможных. Это можно легко избежать, отключив ограничение мономорфизма,
Prelude> :set -XNoMonomorphismRestriction
Prelude> let removeall = filter . (/=)
Prelude> :t removeall
removeall :: (Eq a) => a -> [a] -> [a]
Ответ 2
Также стоит отметить, что если вы не назначаете имя выражению, typechecker, похоже, избегает типа defaulting:
Prelude> :t filter . (/=)
filter . (/=) :: (Eq a) => a -> [a] -> [a]