2014-07-21 29 views
3

中执行类型推断我通过Paul Hudaks强烈推荐的书Haskell School of Expression工作。 在13:EqShowNumFractionalFloating,但这些it's只有一个函数中:日章我碰到这个定义ghc如何在

type Time = Float 

newtype Behavior a = Beh (Time -> a) 

作者声明的NEWTYPE Behavior的几个实例绊倒这些实例声明的一个是窃听我:

instance Num a => Num (Behavior a) where 
    (+) = lift2 (+)         -- This one! 
    fromInteger = lift0 . fromInteger 

lift0 :: a -> Behavior a 
lift0 x = Beh (\t -> x) 

lift2 :: (a -> b -> c) -> (Behavior a -> Behavior b -> Behavior c) 
lift2 g (Beh a) (Beh b) 
    = Beh (\t -> g (a t) (b t))      -- Or actually this one. 

time :: Behavior Time 
time = Beh (\t -> t) 

笔者介绍,在此之后,随着这些新功能的声明,我们现在可以写time + 5,从而解除(+)运营商进入行为领域,或以这种方式。这听起来对我很好,所以当我一起阅读时,我点头微笑。突然之间,作者解释说:(time + 5)相当于Beh (\t -> t + 5),这听起来完全是重击。他甚至提供了这种表达式的展开来证明它:

time + 5 
==> { unfold overloadings for time, (+), and 5 } 
(lift2 (+)) (Beh (\t -> t)) (Beh (\t -> 5)) 
==> { unfold lift2 } 
(\ (Beh a) (Beh b) -> Beh (\t -> a t + b t)) (Beh (\t -> t)) (Beh (\t -> 5)) 
==> { unfold anonymous function } 
Beh (\t -> (\t -> t) t + (\t -> 5) t) 
==> { unfold two anonymous functions } 
Beh (\t -> t + 5) 

这更具体地是我有什么麻烦理解。对我来说正确的说法是:time + (Beh 5)相当于Beh (\t -> t + 5)。但是当我推断出ghci的类型时,它告诉我(当然)作者是正确的,而且我以某种正式的方式愚蠢。有人可以向我解释吗?

+0

'贝5'将是错误的。它应该是'Beh(const 5)',因为'5'不是一个函数。 –

+4

我认为你真正的问题是你错过了['fromInteger'](http://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#v:fromInteger)部分的' Num'类 - 这是将'5'包装到'Behaviour'中的地方;) – Carsten

+1

表达式'time + 5'实际上等于'Beh(\ t→t +(5 t))'。查看'Num(行为a)'的'fromInteger'方法。关键的一点是整数文字有一个隐含的'fromInteger',所以当你写5时,它实际上是'fromInteger(5 :: Integer))'。 – augustss

回答

5

(+)有型号Num a => a -> a -> a。这里aBehavior Float。代码中的文字5被转换为Behavior Float,其中fromInteger应该看起来像fromInteger n = Beh (\t -> fromInteger n)

Beh 5不会检测自Beh包装Float -> a类型的函数,而不是数字。

+0

是的,现在我明白了......谢谢 – patriques