"Yield from" in 哈斯克尔管道



在 Haskell Pipes 中,假设我正在写f :: Producer a m ()并且我在关于m的 do 块内(编辑:这没有意义;我想要一个生产者做块)。在这个 do 块中,我想在返回我的 do 块之前从g :: Producer a m ()中屈服。我该如何做到这一点?

在我的特殊情况下,a = ()m = State s,以及我的生产者正在管理一些只影响状态的分支行为。g碰巧只产生一次,所以在 Python 语言中,它是一个上下文管理器,它会改变一些状态,生成,然后为自己清理。所以在Python中,我可以"从g中产生"或在g上使用@contextmanager并输入一个with块。

编辑:我正在寻找的是为回溯函数编写分支,例如

do
whenM accept_this_one (lift move_to_next)
forM_ choices i -> 
when (notM (bad_choice i)) (lift (select i))

g就像select i,所以把g当成i_type -> Producer () m ()

move_to_nextselect都像上下文管理器一样,清理自己。所以状态变化从move_to_next应该持续到(块的结束?在这里我很困惑。但肯定比单行长。这应该提供可以迭代的东西,并为您管理状态。

在回答关于状态如何受到影响的问题时,f应该合并来自g的状态更改,就像我们在 Python 中所说的那样,如果我们说yield from gfg可以访问公共状态。

编辑2:这是我想要的Python版本:

@contextmanager
def move_to_next():
# do stuff
yield
# undo stuff
return
@contextmanager
def selected(i):
# do stuff
yield
# undo stuff
return
if accept_this_one():
cm = move_to_next()
else:
cm = contextlib.nullcontext()
with cm:
for i in choices:
if not bad_choice(i):
with selected(i):
# Do stuff if you want
yield

编辑3:也许是这个?

select : i_type -> Prod () m ()
move_to_next : Prod () m ()
accept_this_one : m bool
do
let x = ifM (lift accept_this_one)
then move_to_next
else yield
x ~> _ -> forM_ choices i -> 
when (notM (bad_choice i)) (select i)

yield(在这种情况下有效)的类型为a -> Producer a m ()。你不能在mdo块中使用它,只能在Producer a m ()do块中使用它。如果需要使用State,则需要先将其liftProducer

f :: Producer s (State s ()) ()
f = do
x <- lift get
yield x

最新更新