Haskell 函数可以序列化吗?
Posted
技术标签:
【中文标题】Haskell 函数可以序列化吗?【英文标题】:Can Haskell functions be serialized? 【发布时间】:2013-07-21 02:09:39 【问题描述】:最好的方法是获取函数的表示(如果可以以某种方式恢复)。出于效率原因,首选二进制序列化。
我认为在 Clean 中有一种方法可以做到这一点,因为 iTask 无法实现,它依赖于在服务器再次运行时可以保存并继续执行任务(以及功能)。
这对于分布式haskell计算一定很重要。
我不是在寻找在运行时解析 haskell 代码,如下所述:Serialization of functions in Haskell。 我还需要序列化,而不仅仅是反序列化。
【问题讨论】:
另请参阅Haskell for all: The internet of code 以获得(理论上的)建议如何编码函数以发送它们。 【参考方案1】:不幸的是,当前的 ghc 运行时系统无法实现。 函数和其他任意数据的序列化需要一些 ghc 实现者不愿添加的低级运行时支持。
序列化函数要求您可以序列化任何内容,因为任意数据(已评估和未评估)可以是函数的一部分(例如,部分应用程序)。
【讨论】:
【参考方案2】:没有。然而,CloudHaskell 项目正在推动 GHC 中对显式闭包序列化支持的需求。 CloudHaskell 最接近显式闭包的是 distributed-static 包。另一种尝试是HdpH closure representation。但是,两者都以 Thomas describes below 的方式使用 Template Haskell。
限制是 GHC 缺乏静态支持,目前有一个未处理的GHC ticket。 (有接受者吗?)。 CloudHaskell 邮件列表上有 a discussion 说明静态支持的实际外观,但据我所知,还没有任何进展。
最接近设计和实现的人是 Jost Berthold,他在 Eden 中实现了函数序列化。请参阅他的 IFL 2010 论文 "Orthogonal Serialisation for Haskell"。序列化支持已融入 Eden 运行时系统。 (现在作为单独的库提供:packman。不确定它是否可以与 GHC 一起使用,或者需要像 Eden fork 中那样打补丁的 GHC...)GHC 需要类似的东西。这是从 GHC 7.4 派生的版本中的序列化支持 Eden:
data Serialized a = Serialized packetSize :: Int , packetData :: ByteArray#
serialize :: a -> IO (Serialized a)
deserialize :: Serialized a -> IO a
所以:可以序列化函数和数据结构。 Serialized a
有一个 Binary
实例,允许您检查点长时间运行的计算以归档! (参见第 4.1 节)。
在 GHC 基础库中支持这样一个简单的序列化 API 肯定是分布式 Haskell 编程的圣杯。它可能会简化分布式 Haskell 风格之间的可组合性(CloudHaskell、MetaPar、HdpH、Eden 等等......)
【讨论】:
我很惊讶 CloudHaskell 没有硬着头皮添加必要的低级位。 augustss:关于什么是正确的低级位存在一些争议!我们中的许多人都不喜欢原始论文中描述的“传递指针”语义。您对您认为合适的“低级位”的意见将非常受欢迎,因为我知道您已经为这个问题制定了至少一个生产就绪的答案。 @sclv 严格评估会更容易一些。然后,您只需传输值,而通过惰性求值,您可以选择何时何地进行求值。 HdpH 的闭包似乎更强大,并且更接近于发送您想要的任何计算(在我阅读 macs.hw.ac.uk/~pm175/papers/Maier_Trinder_IFL2011_XT.pdf 后的印象之后)。来自 Cloud Haskell 的“简单”闭包似乎仅限于发送***函数和序列化并因此 强制 环境。所以如果你想发送一个部分评估的 expr 你就有麻烦了。 HdpH 引入了闭包组合,因此如果您将代码编写为闭包组合(而不是函数),您必须能够“深入”掌握 expr 结构,不是吗? 跟进。上述票ghc.haskell.org/trac/ghc/ticket/7015 已关闭。 StaticPtr 现在是 GHC 7.10.x 的一部分。【参考方案3】:查看Cloud Haskell。它有一个名为Closure
的概念,用于以类型安全的方式发送要在远程节点上执行的代码。
【讨论】:
注意 cloud haskell 实际上并不发送代码,只是一个环境和索引值,假设一个正确设置的合作伙伴,可用于查找感兴趣的例程。【参考方案4】:Eden 可能最接近并且可能值得单独回答:(De-) 未评估的 thunk 的序列化是可能的,请参阅 https://github.com/jberthold/packman。
然而,反序列化仅限于同一程序(其中程序是“编译结果”)。由于函数被序列化为代码指针,因此无法反序列化以前未知的函数。
可能的用法:
存储未评估的工作以备后用 分发工作(但不共享新代码)【讨论】:
【参考方案5】:一个非常简单实用但可能不那么优雅的解决方案是(最好让 GHC 自动)将每个函数编译成一个独立于机器的字节码模块,在需要序列化该函数时序列化该字节码,并使用dynamic-loader
或 plugins
包,动态加载它们,因此甚至可以使用以前未知的功能。
由于一个模块记录了它的所有依赖项,因此它们也可以被(反)序列化和加载。在实践中,序列化索引号并附加字节码 blob 的索引列表可能是最有效的。
我认为只要你自己编译模块,这已经是可能的了。
正如我所说,它不会很漂亮。更不用说从不安全的来源反序列化代码以在不安全的环境中运行通常会带来巨大的安全风险。 :-) (当然,如果它是值得信赖的就没有问题。)
不过,我现在不打算在这里编写代码。 ;-)
【讨论】:
以上是关于Haskell 函数可以序列化吗?的主要内容,如果未能解决你的问题,请参考以下文章