为什么Haskell没有概括某些函数

时间:2013-10-08 17:31:42

标签: haskell types

我在文件中有以下内容:

import Control.Monad
ema a = scanl1 $ \m n -> (1-a)*m + a*n
macd  = ema 9 . uncurry (zipWith (-)) . liftM2 (,) (ema 26) (ema 12)

在编译时,我得到以下内容:

:t macd
macd :: [Integer] -> [Integer]

然而,

:t ema 9 . uncurry (zipWith (-)) . liftM2 (,) (ema 26) (ema 12)
ema 9 . uncurry (zipWith (-)) . liftM2 (,) (ema 26) (ema 12)
  :: Num a => [a] -> [a]

那么,为什么macd更受限制的类型存在差异?

1 个答案:

答案 0 :(得分:10)

这是单态限制。

要点是,当你有一个受约束的类型变量时,如果Haskell绑定到一个标识符,它将不会推广

f = term

但是,如果它是一个功能绑定,例如

f a ... = term

然后它被推广。我已经回答了这个问题,我在blog post

中写了一个更完整的例子

至于为什么我们有单态限制,

-- let's say comp has the type [Num a => a]
foo = (comp, comp)
  where comp = super_expensive_computation

comp计算多少次?如果我们自动推断一般类型,它可以计算两次。但是,如果你写了类似于Num a => (a, a)或类似类型的东西,那么这可能会让你感到惊讶。

额外的计算是因为在核心土地上像

foo :: Num a => a

变成了更像

的东西
 foo :: NumDict -> a -- NumDict has the appropriate functions for + - etc
                     -- for our a

一个功能。由于foo的一般类型为(Num a, Num b) => (a, b),除非GHC可以证明NumDict在两种情况下comp得到的comp是相同的,它不能分享结果{{1}}