Haskell 有没有一种方法可以捕捉do符号中的连续体?
由于以下原因,请执行以下操作:Haskell 有没有一种方法可以捕捉do符号中的连续体?,haskell,types,continuations,coroutine,continuation-passing,Haskell,Types,Continuations,Coroutine,Continuation Passing,由于以下原因,请执行以下操作: do x <- foo y <- bar return x + y \x->…和y->…实际上不是在这里继续吗 我想知道是否有一种方法可以捕获bind定义中的continuations,但我无法获得正确的类型。即: data Pause a = Pause a | Stop instance Monad Pause where return x = Stop m >>= k = Pause k --
do
x <- foo
y <- bar
return x + y
\x->…
和y->…
实际上不是在这里继续吗
我想知道是否有一种方法可以捕获bind
定义中的continuations,但我无法获得正确的类型。即:
data Pause a = Pause a | Stop
instance Monad Pause where
return x = Stop
m >>= k = Pause k -- this doesn't work of course
现在我试着用这些类型混日子:
data Pause a = Pause a (a -> Pause ???) | Stop
------- k ------
但这也不行。没有办法捕捉这些隐含的延续吗
顺便说一句,我知道monad,我只是在试验和尝试一些东西。好的,我不是很确定,但让我想想。我不太清楚它是什么 应该意味着捕捉延续。例如,您可以捕获整个
do
结构中的块:
{-# LANGUAGE ExistentialQuantification #-}
import Control.Monad
data MonadExp b = Return b | forall a. Bind (MonadExp a) (a -> MonadExp b)
instance Monad MonadExp where
return x = Return x
f >>= g = Bind f g
例如:
block :: MonadExp Int
block = do
x <- return 1
y <- return 2
return $ x + y
instance Show (MonadExp a) where
show (Return _) = "Return _"
show (Bind _ _) = "Bind _ _"
print block
>> Bind _ _
或者一步一步地穿过它,看看它的各个部分
step :: MonadExp a -> MonadExp a
step (Return _) = error "At the end"
step (Bind f g) = g $ finish f
print $ step block
>> Bind _ _
print $ step $ step block
>> Return _
好吧,现在我想得更多了,这可能不是你要问的。但是
也许这会帮助你思考。嗯,我不知道你的lambda是否是这个术语最严格意义上的延续,但在我看来,它们也与这个概念相似 但是请注意,如果它们是连续的,那么被删除的一元代码已经是以连续传递样式(CPS)编写的。“捕获”延续的控制运算符的通常概念是基于直接样式的程序;“捕获的”延续仅在直接样式程序中是隐式的,但CPS转换使其显式 由于被删除的一元代码已经存在于CPS或类似的东西中,那么,一元代码是否能够表达CPS代码所能表达的一些控制流技巧,也许是一种解决问题的方法。通常,这些技巧可以归结为这样一种想法:在CPS机制下,函数通过调用其延续来完成是一种惯例,而函数可以选择用它选择的另一个延续来替换它的延续。此替换延续可以参照原始延续进行构造,这样,如果选择,它可以依次“恢复”原始延续。例如,协程被实现为一个相互的“替换/恢复”循环 从这个角度来看,我认为你的答案大多是否定的;CPS要求在
foo>=bar
中,foo
必须能够选择是否调用bar
,并且foo
必须是缩写,以提供bar
的替代品,但是(>=)
本身并没有提供foo
执行此操作的机制,更重要的是,(>=)
控制执行流,而不是foo
。一些特定的monad实现了它的部分或全部(例如,可能
monad允许foo
通过生成无
结果来放弃执行条
),但其他monad则不这样做
我能得到的最接近的方法是放弃(>>=)
,改用这个:
-- | Execute action @foo@ with its "continuation" @bar@.
callCC :: Monad m => ((a -> m b) -> m b) -> (a -> m b) -> m b
foo `callCC` bar = foo bar
这里
foo
可以选择是否使用bar
。但是请注意,这个callCC
实际上只是($)
我不确定,但也许你需要更仔细地思考你所说的“捕捉延续”是什么意思。看看你对>=
的定义:它扔掉了第一个参数。。。那么第一个论点在那里做什么呢?这正是我想要做的——存在类型是缺失的环节。谢谢
step :: MonadExp a -> MonadExp a
step (Return _) = error "At the end"
step (Bind f g) = g $ finish f
print $ step block
>> Bind _ _
print $ step $ step block
>> Return _
-- | Execute action @foo@ with its "continuation" @bar@.
callCC :: Monad m => ((a -> m b) -> m b) -> (a -> m b) -> m b
foo `callCC` bar = foo bar