为什么 CloudHaskell 中仍然使用远程表和 StaticLabels?

Why remote tables and StaticLabels are still used in CloudHaskell?

我正在阅读 distributed-process 和相关包的源代码。 在 distributed-static 中我们有 StaticLabel 的定义:

data StaticLabel =
    StaticLabel String
  | StaticApply !StaticLabel !StaticLabel
  | StaticPtr SDynamic
  deriving (Eq, Ord, Typeable, Show)

然后用于将 Static 定义为新类型包装器 StaticLabel 为类型安全附加了一个虚拟变量:

newtype Static a = Static StaticLabel
  deriving (Eq, Ord, Typeable, Show)

我对 StaticApply 没有任何疑问,它只是将两个静态混为一谈 值。然而,StaticLabelStaticPtr 似乎达到了同样的目的 以不同的方式。

如果我们使用 StaticLabel 我们只是 have/transimt 一个 String 标签 然后可用于从 RemoteTable:

中查找 Dynamic
newtype RemoteTable = RemoteTable (Map String Dynamic)

其中 Dynamic 是(在 rank1dynamic 中定义):

data Dynamic = Dynamic TypeRep GHC.Any

这与 StaticPtr 中包含的 SDynamic 几乎相同:

data SDynamic = SDynamic TypeRep (StaticPtr GHC.Any)

不同之处在于,Dynamic 我们 GHC.Any 没有间接寻址, 使用 SDynamic 我们必须查找值。结果是一样的:我们收到 如果目标 TypeRepAny 我们可以 unsafeCoerce 的值 instanceOf 我们存储在 SDynamicDynamic.

中的 TypeRep

远程表的管理,虽然在某种程度上是通过 TH 自动化的,但是 仍然有点烦人,那么为什么不只使用 StaticPtrs 呢? StaticLabel 存在只是为了与旧的 GHC 向后兼容,或者我错过了 什么东西?

这样做的主要原因之一是我们必须具有向后兼容性并支持 GHC 的 3 个主要版本。如果我们想立即跳入静态指针解决方案,也不是很明显。例如他们的 "stability" 较弱。基本上唯一的保证是对于相同版本的编译器、库和相同的源代码——静态指针将被编译为相同的值。实际上分布式进程是在考虑到这一点的情况下定义的,但是有些人希望拥有更稳定的指针和静态标签,因为您可以为标签定义自己的规则并且即使在不同的可执行文件中也具有相同的标签。

如果静态指针的保证对您来说足够了,那么还有 distributed-closure 包,它提供了基于静态指针的函数引用。有了这个包,你根本不需要使用 remotetable,只为了分布式进程内部和向后兼容性而保留它。