问题标签 [haskell-polysemy]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
210 浏览

haskell - Extracting multiple IO exceptions into polysemy

Let's say I have some very complex set of computations of the form computation :: IO a that I cannot modify, due to it being from some library code or other reasons. Let's also say I want to provide some type-level guarantees that we aren't able to launch nuclear missiles in the midst of using these computations, so we use polysemy and wrap all these up into its own DSL Library. We can naively interpret this with

This is all well and good, but computation can throw exceptions! We quickly throw up some code and are able to lift a single type of exception into polysemy. We write the helper

and then our interpreter becomes

but we quickly notice this is not extensible. In particular, we are only able to lift a single type of exception, and it's limited to computations in IO. We cannot dive arbitrarily deep into a monad that contains exceptions and transfer it out in a nice and pure manner. If for whatever reason we discover a corner case where computation may throw MyException', we have no way of inserting support for this and catching it elsewhere in our code!

Is there something I am missing in the library that allows me to do this? Am I stuck with dealing with exceptions in IO? Some guidance on where to go forward from here and make this sufficiently polymorphic would be greatly appreciated.

0 投票
1 回答
216 浏览

haskell - Hint.interpret 用于 Polysemy.Sem 值时会出现编译器错误

我正在尝试使用提示( Language.Haskell.Interpreter)在运行时编译Polysemy monad 值。

当我尝试这样做时,我可靠地得到一个关于:在“交互式”代码中不当使用运算符的错误;似乎传递给 GHC 的文本提示中有语法错误。

运行上面的打印:

一些注意事项:

  • 我正在使用 cabal,为了import在解释器 monad 中传递该行,我必须从 cabal 沙盒外壳中运行它,因为 Polysemy 没有安装到我的机器上。
  • 也就是说,我不认为 cabal 或进口 Polysemy 是问题。如果我只是忽略导入 Polysemy 而只是setImportsQ [("Prelude", Nothing)].
  • 我正在解释的字符串甚至不需要是一个有效的表达式;我可以在不更改错误的情况下将乱码放在那里。这向我表明问题出在(as :: MyEffect).
  • 我包括typeOf证明那MyEffect是事实Typeable
  • 我不知道为什么typeOf exampleSem要给出如此长而奇怪的类型签名。我确实认为这在某种程度上是问题所在。重新排列MyEffecttype MyEffect = Sem ((Embed IO) : []) ()没有效果。

如果我做错了什么,任何人都清楚吗?我应该如何尝试调试这个问题?假设这是Type.Reflection.Typeable
中的提示、多义或(不太可能)中的错误,我下一步将如何尝试修复它?我想我必须以某种方式确定哪个库有问题?

这是对先前问题的改进。这是原文。

0 投票
1 回答
133 浏览

haskell - 在 Polysemy 中将一元值转换为 IO

我正在尝试使用webdriverpolysemy在 Haskell 中构建一个自动化功能测试套件。我已经定义了适当的效果并将它们解释为 webdriver WD monad,但现在我被卡住了。

我有一个类型的值,我的自定义功能Member BrowserMaster r => Sem r ()在哪里。BrowserMaster

这是口译员:

现在我想知道如何将Embed WD.WD效果转换为Embed IO,所以我最终只有一个。

我试图制作一个口译员:

(这里runSession chromeConfig . finallyClose是一个WD a -> IO a

它确实有效,但它似乎为每个命令启动了一个新的浏览器会话,而不是只启动一次,在内部完成所有操作并关闭。

我有一种直觉,它必须与资源获取和释放有关,但我无法理解这一点,以便能够将它们放在一起。

0 投票
1 回答
89 浏览

haskell - 在 Polysemy 中运行一次 NonDet 效果

我对 Polysemy 比较陌生,我正在努力思考如何NonDet正确使用。具体来说,假设我有这个计算

这是打印数字 100 的一种非常低效的方法,但它说明了我遇到的问题。现在,我只想在获得第一次成功的情况下运行此效果。也就是说,我想运行这个效果足够长的时间以“找到”数字 100 并打印它,然后我想停止。

我的第一次尝试

这个没有短路。它打印了 100,但随后永远挂起,再次寻找数字 100。那讲得通; 毕竟,我实际上并没有告诉它我只想要一个解决方案。所以让我们试试吧。

我的第二次尝试

我们在这里所做的只是丢弃列表头部以外的所有内容。可以理解的是,这并没有改变任何东西。Haskell 已经不在评估列表,因此丢弃未使用的值不会改变任何事情。就像attempt1,这个解决方案在打印 100 之后永远挂起。

我的第三次尝试

所以我尝试使用runNonDetMaybe. 不幸的是,这个只是退出而不打印任何东西。弄清楚为什么要花一点时间,但我有一个理论。文件说

与 runNonDet 不同,如果第一个选项成功,使用 <|> 根本不会执行第二个分支。

所以它是贪婪的,并且在成功后不会回溯,基本上。因此,它像这样运行我的计算。

非解决方案

在这个小例子中,我们可以稍微改变一下计算,就像这样

因此,与其生成一个数字然后再检查它,我们只需移动generatecomputation. 有了这个computationattempt3成功了,因为我们可以在不回溯的情况下得到“正确”的答案。这在这个小例子中有效,但对于更大的代码库是不可行的。除非有人有一种很好的系统方法来避免回溯,否则我看不出有一种很好的方法可以将此解决方案推广到跨越大型程序中的多个文件的计算。

另一个非解决方案是使用IO.

现在成功了,因为我们只是在成功后强行退出程序attempt1attempt2但是,除了感觉非常草率之外,这也不能一概而论。我想在找到 100 后停止运行当前计算,而不是整个程序。

因此,总而言之,我希望使用 Polysemy 以某种方式运行上面第一个代码片段中给出的计算,这会导致它回溯(in NonDet)直到找到一个成功的值(在上面的示例中n = 100),然后停止运行影响并结束计算。我尝试深入研究runNonDetMaybeand co 的源代码,希望能够重现具有我想要的效果的类似于它的东西,但是我的多义词技能还没有达到理解那里发生的所有恶作剧Weaving的水平。decomp我希望这里比我更了解这个库的人可以为我指明正确的方向,NonDet以实现所需的效果。

0 投票
1 回答
60 浏览

haskell - 多义词未检测到成员

Sem我正在尝试在单个多义的Monad 中使用 Hspec 编写一堆语句,如下所示:

在明确指定时,Storage Book Member我有以下错误:

我看不出我能做些什么来帮助类型检查器。

0 投票
2 回答
144 浏览

haskell - 在多义词中使用 pooledMapConcurrentlyN

我目前正在玩 Polysemy,重写我的一个小玩具项目以适应它。我偶然发现了一段使用 的代码pooledMapConcurrentlyN,因此基本上是具有有限并发的并行版本。

我可以将我的示例简化为:

这不会编译,因为没有MonadUnliftIO (Sem r). 它在我使用时会编译traverse,但我正在寻找一个并发版本。我不确定我现在应该走哪条路。

我看到以下选项:

  • 实现一个MonadUnliftIO (Sem r)实例。我看到在这个 GitHub issue中有一些关于添加/实现这样一个实例的讨论。但是,我不清楚这样做是否是个好主意。
  • 使用除此之外的东西pooledMapConcurrentlyN会给我一个等效的行为。我知道有parTraverse来自par-dual包,但这需要一个ParDual实例。该parallel软件包也可以使解决方案成为可能,但是我对此并不熟悉,因此无法确定是否可行。
  • 将平行遍历建模为效果。我试过了,但我无法实现效果。我试过的效果定义是这样的:

我对 GADT 和 Polysemy 都不是很熟悉,所以我可能在这里遗漏了一些明显的东西。


编辑:正如下面的答案所指出的,最合适的解决方案是将其建模为效果并在效果解释中处理并发,而不是在业务逻辑中处理。这意味着我正在寻找类似于上述ParTraverse效果的更高阶效果(?):

我不确定这种类型签名是否正确(动作应该有 typea -> Sem r b吗?for 的签名traverse有一个Applicative约束m,我将如何建模?)

0 投票
0 回答
78 浏览

haskell - 将 `Sem (x ': r) a` 解释为 `Sem (y ': r) b`?

我正在尝试将机器组合在一起,以使用代数效应编写诸如秘密共享(例如)之类的东西。更具体地说,我希望能够根据每一方的行动来编写协议,然后将那个效果空间处理成模拟一些相互交谈的演员。

我想使用代数效应是因为我觉得它很酷,而且我认为它对后续的一些分析会有帮助。Polysemy似乎是一个不错的库选择。

例如,考虑三方试图获取其秘密输入总和的简单情况。我们可能会写类似

(上面是否有任何好处都很好知道,但不是这里的问题。一旦你让 Stack 编译 polysemy-zoo,它就会进行类型检查。

我将如何为效果编写处理程序Communication3

如果我们想象我们正在尝试将其实现为互联网协议,那么“可执行文件”看起来很像我们编写的代码;消息将被处理到通过网络发送和接收数据的任何过程中。
我也(事实上,主要是)希望能够在本地模拟三方。这意味着,粗略地说,我需要编写一个处理程序/解释器/运行器,例如

表示并行运行整个事情三次(大部分)。

显然这是可以做到的;处理State程序会这样做。但我还没有找到任何关于如何的文档。我应该在哪里寻找?我错过了什么?

0 投票
0 回答
99 浏览

haskell - 多义表达式的惰性相互递归求值

注意:我认为这里的问题不在于 Polysemy本身

目标:

我正在尝试编写多方同步通信的单线程模拟。更具体地说,目标是编写一个方将在某个效果系统中运行*的程序**,并具有一个纯函数,可以模拟多方一起运行他们的程序。该模拟的输出应该是各方发送(或接收)的所有消息的表示***。

*所有各方将运行相同的程序。
**多义词是我所知道的。
***以及每一方各自的返回值,尽管这并不重要。

设置:

我们可以稍微简化一下,假设只有两方。对于这种情况,我写了一个简单的Pair仿函数;对于实际系统,我希望使用固定长度的向量。

我们感兴趣的特定效果是InputOutput
output $ Pair a1 a2表示“相关方”发送a1给方#1 和a2方#2。
Pair b1 b2 <- input表示“相关方”b1从方#1 和b2方#2 接收。
这些总是必须成对出现,output首先是。在实际系统中,我们会通过处理和处理的Communicate效果来保证这一点,但现在我们只是将其作为假设。 InputOutput

我认为不可能完全在 Polysemy 处理程序(也称为解释器或运行器)的结构中进行我想要的那种并行同步模拟。我很确定我需要的是一个像

第一个参数parallelEvaluation只是一个垫片;我可能不需要它。

理念:

如果我们想象两方并行运行,我们可以清楚地收集output他们发送的 s;Polysemy 已经为此内置了处理程序。这将为我们提供我们想要的东西:所有已发送消息的列表。
问题是向他们input的 s 提供什么。

这个想法是使用parallelEvaluation递归的结果作为处理程序的输入磁带Inputoutput如果整个函数是“足够”惰性的,并且我们上面关于和总是一起出现的假设input是合理的,那么这应该是可计算的。

多义词必要的懒惰!
具体看这里doRealRecursion 工作正常;我为使它工作所做的唯一特别的事情是使用runLazyOutputList处理程序(出于空间效率的原因,这不是 Polysemy 的默认设置)。

编码:

测试纯并行模拟

Pair帮手_

问题:

作为可执行文件,doParallelRecursion打印"Attempting..."(使用换行符),然后挂起(似乎永远)。

从 GHCI,它打印

然后在那条线上挂了几秒才*** Exception: stack overflow

我尝试使用 GHCI 中的调试器来缩小问题范围。假设我正确使用它,runUnsafeInputList并且testProgram从未被评估过。runUnsafeInputList <$> os评估os,立即递归。

我试过交换效果/处理程序的顺序,这根本不影响行为。(我认为这无关紧要,但这里呈现的顺序可能更直观。)

0 投票
1 回答
118 浏览

haskell - 如何将 MTL 风格、CPS 风格的高阶效果融入多义词中?

我正在将代码库转换为使用polysemy ,并且在转换我对LFreshtypeclass 的unbound-generics使用时遇到了麻烦。我需要的两个操作都有签名

这显然是高阶的。我想创建一个与LFresh该类对应的效果,并LFreshM通过unbound-generics. 到目前为止,这是我尝试过的,Final因为这似乎让我比父亲更喜欢Embed(我很高兴LFreshM一直是效果堆栈中的最后一件事):

但是, case forLUnbind不进行类型检查,因为k' :: f (p, t) -> U.LFreshM (f x)它期望某种类型(p, t) -> U.LFreshM (f x)作为 ; 的第二个参数U.lunbindf注意类型中的额外内容k'

我还有其他模糊的想法,但我暂时将其留在那里,很高兴进一步澄清。甚至不确定我是否走在正确的轨道上。最终,我的真正目标只是“让多义词与LFreshfrom一起工作unbound-generics”,所以如果有更好的、完全不同的方法来实现,我也很高兴听到它。

0 投票
1 回答
43 浏览

haskell - 无法提高下

我尝试使用raiseUnder(使用多义词 1.6.0)来引入效果以使用其他解释器,例如:

虽然我希望它只是注入一个新的效果:

我收到此错误: