15

这个问题的灵感来自另一个问题的答案,表明您可以使用定义为的函数从列表中删除每个出现的元素:

removeall = filter . (/=)

用铅笔和纸从 和 的类型中计算出来,filter函数的类型为(/=)(.)

removeall :: (Eq a) => a -> [a] -> [a]

这正是您根据其合同所期望的。但是,使用 GHCi 6.6,我得到

gchi> :t removeall
removeall :: Integer -> [Integer] -> [Integer]

除非我明确指定类型(在这种情况下它可以正常工作)。为什么 Haskell 会为函数推断出如此特定的类型?

4

2 回答 2

28

为什么 Haskell 会为函数推断出如此特定的类型?

GHCi 使用默认类型,从一组可能的情况中推断出更具体的类型。您可以通过禁用单态限制轻松避免这种情况,

Prelude> :set -XNoMonomorphismRestriction
Prelude> let removeall = filter . (/=)
Prelude> :t removeall 
removeall :: (Eq a) => a -> [a] -> [a]
于 2009-08-28T02:09:33.397 回答
17

还值得注意的是,如果您不为表达式分配名称,类型检查器似乎会避免类型默认:

Prelude> :t filter . (/=)
filter . (/=) :: (Eq a) => a -> [a] -> [a]
于 2009-08-28T07:09:47.193 回答