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]