给定存在性数据类型,例如:
data Foo = forall a . (Typeable a, Binary a) => Foo a
Run Code Online (Sandbox Code Playgroud)
我想写instance Binary Foo.我可以编写序列化(序列化TypeRep然后序列化值),但我无法弄清楚如何编写反序列化.基本问题是,如果TypeRep你需要映射回该类型的类型字典 - 我不知道是否可以这样做.
之前在haskell邮件列表http://www.haskell.org/pipermail/haskell/2006-September/018522.html上已经提出过这个问题,但没有给出答案.
您需要某种方式,每个Binary实例都可以自己注册(就像在您的witness版本中一样).您可以通过将每个实例声明与导出的外部符号捆绑在一起来实现此目的,其中符号名称来自TypeRep.然后,当你想要反序列化时,你可以从中获取名称TypeRep并动态查找该符号(使用dlsym()或类似的东西).外部导出导出的值可以是例如解串器函数.
这很疯狂,但它确实有效.
这可以在 GHC 7.10 及更高版本中使用静态指针语言扩展来解决:
{-# LANGUAGE StaticPointers #-}
{-# LANGUAGE InstanceSigs #-}
data Foo = forall a . (StaticFoo a, Binary a, Show a) => Foo a
class StaticFoo a where
staticFoo :: a -> StaticPtr (Get Foo)
instance StaticFoo String where
staticFoo _ = static (Foo <$> (get :: Get String))
instance Binary Foo where
put (Foo x) = do
put $ staticKey $ staticFoo x
put x
get = do
ptr <- get
case unsafePerformIO (unsafeLookupStaticPtr ptr) of
Just value -> deRefStaticPtr value :: Get Foo
Nothing -> error "Binary Foo: unknown static pointer"
Run Code Online (Sandbox Code Playgroud)
可以在此博客文章中找到该解决方案的完整描述,并在此处找到完整的代码片段。