2011-09-13 28 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值(即失败)似乎是有意义的。