为什么';t-Haskell推广了一些函数
我有以下文件:为什么';t-Haskell推广了一些函数,haskell,types,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 (,) (e
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
的限制类型不同呢?这就是单态限制
要点是,当您有一个受约束的类型变量时,如果它绑定到一个标识符,Haskell将不会进行泛化
f = term
然而,如果它是一个函数绑定,例如
f a ... = term
然后对其进行了推广。这个问题我已经回答得够多了,所以我在一篇文章中写了一个更完整的例子
至于为什么我们有单态限制
-- let's say comp has the type [Num a => a]
foo = (comp, comp)
where comp = super_expensive_computation
将计算多少次comp
?如果我们自动推断一般类型,它可以计算两次。但是,如果您编写类似这样的代码,打算使用类型numa=>(a,a)
或类似的代码,您可能会感到惊讶
额外的计算是因为在核心地带
foo :: Num a => a
变成更像
foo :: NumDict -> a -- NumDict has the appropriate functions for + - etc
-- for our a
函数。由于
foo
s的一般类型是(Num a,Num b)=>(a,b)
,除非GHC能够证明comp
在两种情况下得到的NumDict
是相同的,否则它不能作为元注释共享comp
的结果,确实应该有一个明确的“这就是单态限制”我们可以链接到这里的问题我明白了。谢谢解决这个问题的简单方法是emaaxs=scanl1(\mn->(1-a)*m+a*n)xs
和macdxs=ema9。未修剪(带(-)的拉链)。liftM2(,)(ema 26)(ema 12)$xs
@me2是的,或者只是添加类型签名:)通常这是我的建议。它对人类和人类都有帮助compilers@me2Jozefg提到,Num a=>a
被提交到NumDict->a
,如果您想确切了解这是如何实现的,我建议您进行一次精彩的演讲。这是非常容易理解的,您不需要太多haskell知识就可以理解了,最后您将发现TypeClass对于纯数据类型来说是多么的简单。