我正在尝试将机器组合在一起,以使用代数效应编写诸如秘密共享(例如)之类的东西。更具体地说,我希望能够根据每一方的行动来编写协议,然后将那个效果空间处理成模拟一些相互交谈的演员。
我想使用代数效应是因为我觉得它很酷,而且我认为它对后续的一些分析会有帮助。Polysemy似乎是一个不错的库选择。
例如,考虑三方试图获取其秘密输入总和的简单情况。我们可能会写类似
import Polysemy (Member, Members, Sem, makeSem)
import Polysemy.Random (Random, randomR)
data Communication3 s m a where
Message :: (s, s) -> Communication3 s m (s, s) -- Pass a message, and get peers' messages.
Secret :: Communication3 s m s -- Input one's own secret values.
Reveal :: s -> Communication3 s m (s, s) -- Share a value with all peers, and get theirs.
makeSem ''Communication3 -- Uses template haskell to generate:
-- message :: Member (Communication3 s) r => (s, s) -> Sem r (s, s)
-- secret :: Member (Communication3 s) r => Sem r s
-- reveal :: Member (Communication3 s) r => s -> Sem r (s, s)
--------- The "application" code: --------
modulus = 1013 :: Int
modulo = (`mod` modulus)
randomM :: Member Random r => Sem r Int
randomM = randomR (0, modulus - 1)
sumOfSecrets :: Members [(Communication3 Int), Random] r =>
Sem r Int
sumOfSecrets = do
myInput <- secret
noiseB <- randomM
noiseC <- randomM
(shareInB, shareInC) <- message (noiseB, noiseC)
let shareInA = modulo (myInput - noiseB - noiseC)
let shareResultA = modulo (shareInA + shareInB + shareInC)
(shareResultB, shareResultC) <- reveal shareResultA
return $ modulo (shareResultA + shareResultB + shareResultC)
(上面是否有任何好处都很好知道,但不是这里的问题。一旦你让 Stack 编译 polysemy-zoo,它就会进行类型检查。)
我将如何为效果编写处理程序Communication3
?
如果我们想象我们正在尝试将其实现为互联网协议,那么“可执行文件”看起来很像我们编写的代码;消息将被处理到通过网络发送和接收数据的任何过程中。
但我也(事实上,主要是)希望能够在本地模拟三方。这意味着,粗略地说,我需要编写一个处理程序/解释器/运行器,例如
runCommunication3 :: Sem ((Communication3 a) ': r) b -> Sem r (b, b, b)
表示并行运行整个事情三次(大部分)。
显然这是可以做到的;处理State
程序会这样做。但我还没有找到任何关于如何的文档。我应该在哪里寻找?我错过了什么?