Cloud Haskell - 如何为闭包编写"纯粹"?

Cli*_*ton 6 serialization haskell cloud-haskell

我一直在玩Cloud Haskell.我在hackage文档中注意到有一种应用程序界面.但特别是我正在尝试closurePure使用以下签名查找或编写函数:

closurePure :: (Typeable a, Binary a) => a -> Closure a
Run Code Online (Sandbox Code Playgroud)

这基本上是纯粹的限制版本.

虽然Closure数据类型本身是抽象的,但以下closure提供了:

closure :: Static (ByteString -> a) -> ByteString -> Closure a
Run Code Online (Sandbox Code Playgroud)

所以我可以做到这一点:

closurePure :: (Typeable a, Binary a) => a -> Closure a
closurePure x = closure ??? (encode x)
Run Code Online (Sandbox Code Playgroud)

问题是在什么地方放置???.

我的第一次尝试如下:

myDecode :: (Typeable a, Binary a) => Static (ByteString -> a)
myDecode = staticPtr (static decode)
Run Code Online (Sandbox Code Playgroud)

但是在阅读关于静态指针GHC文档时,该show示例向我建议您不能有约束,因为受约束的函数没有Typeable实例.所以我尝试了使用的建议Dict:

myDecode :: Typeable a => Static (Dict (Binary a) -> ByteString -> a)
myDecode = staticPtr (static (\Dict -> decode))
Run Code Online (Sandbox Code Playgroud)

但现在我的错误类型不符合上述closure功能.

无论如何要写closurePure或类似的东西(或者我在Cloud Haskell文档中错过了它)?将binary普通类型提升为Closures对于使用给定的应用界面似乎是必不可少的,但我无法弄清楚如何去做.

请注意,我可以这样做:

class StaticDecode a where
  staticPtrDecode :: StaticPtr (ByteString -> a)

instance StaticDecode Int where
  staticPtrDecode = static Data.Binary.decode

instance StaticDecode Float where
  staticPtrDecode = static Data.Binary.decode

instance StaticDecode Integer where
  staticPtrDecode = static Data.Binary.decode

-- More instances etc...

myPure :: forall a. (Typeable a, StaticDecode a, Binary a) => a -> Closure a
myPure x = closure (staticPtr staticPtrDecode) (encode x)
Run Code Online (Sandbox Code Playgroud)

哪个效果很好,但基本上要求我为每个Binary实例重复一个实例.看起来很乱,我更喜欢另一种方式.

mac*_*ron 4

你是对的,它Closure有一个类似应用程序的结构,这一事实在分布式闭包的接口和实现中都变得更加明确。它不太适用,因为在这种pure情况下,我们确实有额外的约束,即参数必须以某种方式可序列化。

事实上,我们有一个更强的约束。不仅参数必须是可序列化的,而且约束本身也必须是可序列化的。就像很难直接序列化函数一样,您可以想象很难序列化约束。但就像函数一样,技巧是序列化一个指向约束本身的静态指针(如果存在这样的静态指针)。我们怎么知道这样的指针存在呢?我们可以引入一个带有单个方法的类型类,该方法在给定约束的情况下为我们提供指针的名称:

class GimmeStaticPtr c where
  gimmeStaticPtr :: StaticPtr (Dict c)
Run Code Online (Sandbox Code Playgroud)

这里有一个小小的技术技巧。类型索引的种类StaticPtr是 kind *,而约束则具有 kind Constraint。因此,我们重用约束库中的一个技巧,即将约束包装到数据类型中(Dict上面),就像所有数据类型一样*。具有关联GimmeStaticPtr实例的约束称为静态约束

一般来说,有时组合静态约束以获得更多静态约束是有用的。StaticPtr不可组合,但Closure可以。所以distributed-closure实际做的是定义一个类似的类,我们称之为,

class GimmeClosure c where
  gimmeClosure :: Closure (Dict c)   
Run Code Online (Sandbox Code Playgroud)

现在我们可以用closurePure与您类似的方式定义:

closurePure :: (Typeable a, GimmeClosure (Binary a)) => a -> Closure a
Run Code Online (Sandbox Code Playgroud)

如果将来编译器可以GimmeClosure通过根据需要生成静态指针来即时解决约束,那就太好了。但就目前而言,最接近的是 Template Haskell。分布式闭包提供了一个模块,可以GimmeClosure (Cls a)在类的定义站点自动生成约束Cls。看withStatic 这里

顺便说一句,Edsko de Vries就分布式闭包及其所体现的思想进行了精彩的演讲。