2011-09-13 64 views
10

我正在查看Cloud Haskell軟件包的Encoding.hs,並遇到一些奇怪的代碼,我希望有人能幫助我更好地理解。包括的是必要的代碼:haskell魔法代碼,這裏發生了什麼

class (Binary a,Typeable a) => Serializable a 
instance (Binary a,Typeable a) => Serializable a 

data Payload = Payload 
    { 
     payloadType :: !ByteString, 
     payloadContent :: !ByteString 
    } deriving (Typeable) 

serialDecodePure :: (Serializable a) => Payload -> Maybe a 
serialDecodePure a = (\id -> 
    let pc = payloadContent a 
    in pc `seq` 
     if (decode $! payloadType a) == show (typeOf $ id undefined) 
     then Just (id $! decode pc) 
     else Nothing) id 

我只是好奇$什麼! (我猜只是嚴格評估),以及爲什麼我們需要id技巧(有些懶惰評估?)。另外我特別有這個線路問題:

if (decode $! payloadType a) == show (typeOf $ id undefined) 

我猜這是看到如果載荷類型是出於某種原因失效,但如果是這樣的情況下,不應該再和其他條款進行切換,即改變:

if (decode $! payloadType a) == show (typeOf $ id undefined) 
    then Just (id $! decode pc) 
    else Nothing 

if (decode $! payloadType a) == show (typeOf $ id undefined) 
    then Nothing 
    else Just (id $! decode pc) 

感謝您的幫助,您可以提供。

+0

是的,'f $! x'是嚴格的應用程序。你可能會發現[這篇文章](http://neilmitchell.blogspot.com/2008/05/bad-strictness.html)關於如何增加嚴格性的作品。 –

+0

另請參見http://stackoverflow.com/q/2787543/246886 –

回答

12

你是對的,$!是一個嚴格的評估者。它的類型與$相同,唯一的語義區別是第二個參數在傳遞給函數之前是seq'd。

我認爲id實際上有幫助類型推斷。在功能塊(\id -> ...),功能id被迫有a -> a類型,其中a是不是任何類型的變量,但相同a

serialDecodePure :: (Serializable a) => Payload -> Maybe a 

這是由於這一行:

Just (id $! decode pc) 

因爲這種類型是Maybe a,id具有推斷的類型a -> a。因此,上線你看,

if (decode $! payloadType a) == show (typeOf $ id undefined) 

id undefined :: a,其中a又是相同的輸出。

現在我們可以進行類型檢查。由於此功能具有多態性,並且將解碼爲任何類型的,因此需要檢查編碼數據是否與其解碼的類型兼容。如果你編碼String並試圖解碼爲Int會怎麼樣? LHS將解碼爲「[Char]」,這是String的TypeRep表示形式。 RHS將改爲「Int」,即它試圖解碼的類型。由於它們不相等,所以「其他」路徑返回None

而不是這個id函數類型的限制,你可以用ScopedTypeVariables擴展完成同樣的事情。

+1

哦,人的身份證事情是方式聰明 –

4

哇,這是一些奇怪的代碼!正如你猜到了,($!)約爲嚴格:

f $! x = x `seq` f x 

id訣竅是sneakier,並且是所有類型的限制。您會注意到id在函數體中使用了兩次。第二次用作id $! decode pc;這修正了id的類型以對任何類型的東西decode輸出進行操作。第一個用途是typeOf $! id undefined;由於id的類型已被修復,因此修復了undefined的類型,因此typeOf應用於單形變元(並且不會出現「模糊類型」錯誤)。這種事通常是用ScopedTypeVariables擴展來完成的,而不是這個詭計,但也許他們想盡可能地避免擴展。至於這是什麼意思:

(decode $! payloadType a) == show (typeOf $ id undefined) 

...它看起來對我來說,那是檢查的有效載荷由呼叫在then分支回到decode事物的類型相匹配。當它們匹配時具有Just值(即成功)和當它們不匹配時具有Nothing值(即失敗)似乎是有意義的。

相關問題