我一直在玩Cloud Haskell。我注意到in the hackage documentation有一种应用程序界面。但特别是我正在尝试查找或编写具有以下签名的函数closurePure:

closurePure :: (Typeable a, Binary a) => a -> Closure a

这基本上是pure的受限版本。

尽管Closure数据类型本身是抽象的,但提供了以下 closure :
closure :: Static (ByteString -> a) -> ByteString -> Closure a

所以我可以做到这一点:
closurePure :: (Typeable a, Binary a) => a -> Closure a
closurePure x = closure ??? (encode x)

问题是将???放在哪里。

我的第一次尝试是:
myDecode :: (Typeable a, Binary a) => Static (ByteString -> a)
myDecode = staticPtr (static decode)

但是在阅读GHC docs on static pointers时,show示例向我建议您没有约束,因为受约束的函数没有Typeable实例。所以我尝试了建议使用 Dict 的方法:
myDecode :: Typeable a => Static (Dict (Binary a) -> ByteString -> a)
myDecode = staticPtr (static (\Dict -> decode))

但是现在我得到了上面的closure函数不适合的错误类型。

无论如何,有没有要写closurePure或类似的东西(或者我在Cloud Haskell文档中错过了它)?对于使用给定的应用程序接口(interface),将binary普通类型提高为Closure似乎很重要,但是我不知道该怎么做。

请注意,我可以这样做:
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)

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

最佳答案

没错,Closure具有类似应用程序的结构,事实在distributed-closure的接口(interface)和实现中都更加明确。它不是很实用,因为在pure情况下,我们确实具有附加约束,即该参数必须以某种方式可序列化。

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

class GimmeStaticPtr c where
  gimmeStaticPtr :: StaticPtr (Dict c)

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

通常,组合静态约束以获得更多的静态约束有时很有用。 StaticPtr是不可组合的,但Closure是可组合的。所以distributed-closure实际要做的是定义一个类似的类,我们将其称为“
class GimmeClosure c where
  gimmeClosure :: Closure (Dict c)

现在,我们可以按照与您相似的方式定义closurePure:
closurePure :: (Typeable a, GimmeClosure (Binary a)) => a -> Closure a

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

顺便说一句,埃德斯科·德弗里斯(Essko de Vries)发表了关于分布式封闭及其体现的思想的书。

关于haskell - Cloud Haskell-如何为闭包编写 "pure"?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47724724/

10-11 21:12