haskell魔法代码,这里发生了什么

Ani*_*tla 10 syntax binary haskell

我正在查看Cloud Haskell软件包的Encoding.hs,并遇到了一些奇怪的代码,我希望有人可以帮助我更好地理解.包括必要的代码:

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
Run Code Online (Sandbox Code Playgroud)

我只是好奇什么是$!(我猜测只是严格评估),还有为什么我们需要id技巧(懒惰评估的东西?).另外我特意遇到这条线的问题:

if (decode $! payloadType a) == show (typeOf $ id undefined)
Run Code Online (Sandbox Code Playgroud)

我猜这是因为无论出于何种原因,看看payloadType是否无效,但如果是这种情况,则不应切换then和else子句,即更改:

if (decode $! payloadType a) == show (typeOf $ id undefined)
    then Just (id $! decode pc)
    else Nothing
Run Code Online (Sandbox Code Playgroud)

if (decode $! payloadType a) == show (typeOf $ id undefined)
    then Nothing
    else Just (id $! decode pc)
Run Code Online (Sandbox Code Playgroud)

感谢您的任何帮助,您可以提供.

Joh*_*n L 12

你是对的,$!是一个严格的评估者.它的类型是相同的$,唯一的语义差异是第二个参数seq在传递给函数之前是'd'.

我认为id实际上有帮助类型推断.在功能块中(\id -> ...),该函数id被强制为具有类型a -> a,其中a不仅是任何类型变量,而是a in 相同

serialDecodePure :: (Serializable a) => Payload -> Maybe a
Run Code Online (Sandbox Code Playgroud)

这是由于这一行:

Just (id $! decode pc)
Run Code Online (Sandbox Code Playgroud)

由于这有类型Maybe a,id有推断类型a -> a.结果,在你正在看的线上,

if (decode $! payloadType a) == show (typeOf $ id undefined)
Run Code Online (Sandbox Code Playgroud)

id undefined :: a,哪里a再与输出相同.

现在我们可以进行类型检查.由于此函数是多态的并且将解码为任何类型,因此需要检查编码数据是否与其解码的类型兼容.如果您编码String并尝试解码Int为什么怎么办?LHS将解码为"[Char]",这是String的TypeRep表示.RHS将改为"Int",它正在尝试解码的类型.由于它们不相等,所以"else"路径是返回的路径None.

而不是这个id函数类型限制,你可以用ScopedTypeVariables扩展完成相同的事情.