[英]"Yield from" in Haskell Pipes
In Haskell Pipes , suppose I am writing f:: Producer am ()
and I am inside a do block with respect to m
( Edit: this doesn't make sense; I want a producer do block).在Haskell Pipes中,假设我正在编写
f:: Producer am ()
并且我在关于m
的 do 块内(编辑:这没有意义;我想要一个生产者 do 块)。 Inside this do block, I want to yield from g:: Producer am ()
before returning to my do block.在这个 do 块中,我想在返回到我的 do 块之前从
g:: Producer am ()
产生。 How do I accomplish that?我如何做到这一点?
In my particular case, a = ()
and m = State s
, and my producers are managing some branching behavior which only affects the state. g
happens to yield only once, so in Python language, it's a context manager that changes some state, yields, then cleans up for itself.在我的特殊情况下,
a = ()
和m = State s
,我的生产者正在管理一些仅影响 state.g 的分支行为g
恰好只产生一次,所以在 Python 语言中,它是一个上下文管理器,它改变了一些 state,产量,然后自行清理。 So in Python I could "yield from g" or use @contextmanager
on g
and enter a with
block.因此,在 Python 中,我可以“从 g 中产生”或在
g
上使用@contextmanager
并输入with
块。
Edit: What I'm looking for is to write branches for a backtracking function, something like编辑:我正在寻找的是为回溯 function 编写分支,比如
do
whenM accept_this_one (lift move_to_next)
forM_ choices \i ->
when (notM (bad_choice i)) (lift (select i))
g
is like select i
, so think of g
as i_type -> Producer () m ()
. g
就像select i
,因此将g
视为i_type -> Producer () m ()
。
move_to_next
and select
are both like context managers, cleaning up after themselves. move_to_next
和select
都像上下文管理器,自行清理。 So the state changes from move_to_next
should last until (the end of the block? Here I'm confused. But certainly longer than the single line.) This should give something one can iterate over, and it manages the state for you.所以 state 从
move_to_next
的变化应该持续到(块的末尾?在这里我很困惑。但肯定比单行更长。)这应该提供一些可以迭代的东西,它会为你管理 state。
In response to a question about how the state is affected, f
should incorporate state changes from g
, in the way it would in Python if we said yield from g
, and f
and g
had access to common state.在回答有关 state 如何受到影响的问题时,
f
应该合并 g 的 state 更改,如果我们说yield from g
g
f
和g
可以访问公共 state,那么它会在 Python 中这样做。
Edit2: Here's a Python version of what I want: Edit2:这是我想要的 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
Edit 3: Maybe this?编辑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
(effectively, in this context) has the type a -> Producer am ()
. yield
(实际上,在这种情况下)具有类型a -> Producer am ()
。 You cannot use it in the do
block of a m
, only the do
block of a Producer am ()
.您不能在
m
的do
块中使用它,只能在Producer am ()
的do
块中使用它。 If you need to use a State
, you need to lift
it to Producer
first:如果你需要使用一个
State
,你需要先将它lift
到Producer
:
f :: Producer s (State s ()) ()
f = do
x <- lift get
yield x
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.