2014-07-21 53 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