从这个线程(Control.Monad.Cont fun,2005),Tomasz Zielonka介绍了一个函数(由ThomasJäger以清晰而美观的方式评论).Tomasz接受callCC主体的参数(函数)并返回它以供以后使用,具有以下两个定义:
import Control.Monad.Cont
...
getCC :: MonadCont m => m (m a)
getCC = callCC (\c -> let x = c x in return x)
getCC' :: MonadCont m => a -> m (a, a -> m b)
getCC' x0 = callCC (\c -> let f x = c (x, f) in return (x0, f))
Run Code Online (Sandbox Code Playgroud)
这些也在Haskellwiki中提到过.使用它们,你可以像haskell中的goto语义看起来非常酷:
import Control.Monad.Cont
getCC' :: MonadCont m => a -> m (a, a -> m b)
getCC' x0 = …Run Code Online (Sandbox Code Playgroud) 他们是什么,他们有什么好处?
我没有CS学位,我的背景是VB6 - > ASP - > ASP.NET/C#.任何人都能以清晰简洁的方式解释它吗?
我想(一般来说)我的理解shift和reset意思.但是我不明白他们为什么如此命名?什么shift和reset分隔继续原语与英语中的"移位"和"重置"单词有什么关系?
我们有一个非常高性能的多任务处理,近乎实时的C#应用程序.这种性能主要通过在内部与本土调度程序一起实施协作式多任务处理来实现.这通常被称为微线程.在该系统中,所有任务都通过队列与其他任务进行通信.
我们所遇到的具体问题似乎只能通过C#不支持的一流延续来解决.
具体而言,问题出现在处理队列的2个案例中.每当任何特定任务在将项目放入队列之前执行某些工作时.如果队列已满,该怎么办?
相反,一个不同的任务可能会做一些工作,然后需要从队列中取出一个项目.如果那个队列是空的怎么办?
我们已经在90%的情况下通过将队列链接到任务来解决这个问题,以避免在任何出站队列已满或入站队列为空时调用任务.
此外,某些任务被转换为状态机,因此如果队列已满/空,它们可以处理并继续而无需等待.
真正的问题出现在一些边缘情况下,其中任何一种解决方案都是不切实际的.在这种情况下的想法是在该点保存堆栈状态并切换到另一个任务,以便它可以完成工作,并随后在能够继续时重试等待任务.
在过去,我们尝试将等待任务调用回调度(递归)以允许其他任务以及稍后重试等待任务.然而,这导致了太多的"僵局"情况.
有一个自定义CLR主机的示例,使.NET线程实际上作为"光纤"运行,这实际上允许在线程之间切换堆栈状态.但现在我似乎无法找到任何示例代码.此外,似乎需要一些重要的复杂性才能做到正确.
有没有人有任何其他创意,如何有效地切换任务,避免上述问题?
是否有其他CLR主机提供此商业或其他?是否有任何附加本机库可以为C#提供某种形式的延续?
Set,类似于[]具有完美定义的monadic操作.问题是它们要求值满足Ord约束,因此不可能定义return并且>>=没有任何约束.同样的问题适用于需要对可能值进行某种约束的许多其他数据结构.
标准技巧(在haskell-cafe帖子中向我建议)是包含Set在延续monad中.ContT并不关心底层类型仿函数是否有任何约束.只有在将Sets 包装/展开到continuation中时才需要约束:
import Control.Monad.Cont
import Data.Foldable (foldrM)
import Data.Set
setReturn :: a -> Set a
setReturn = singleton
setBind :: (Ord b) => Set a -> (a -> Set b) -> Set b
setBind set f = foldl' (\s -> union s . f) empty set
type SetM r a = ContT r Set a
fromSet :: (Ord r) => Set a …Run Code Online (Sandbox Code Playgroud) 我正在阅读有关列表操作的一些技巧,其中包含以下内容:
Run Code Online (Sandbox Code Playgroud)zipRev xs ys = foldr f id xs snd (ys,[]) where f x k c = k (\((y:ys),r) -> c (ys,(x,y):r))我们在这里可以看到,我们有两个连续的叠放在一起。发生这种情况时,他们通常可以“取消”,如下所示:
Run Code Online (Sandbox Code Playgroud)zipRev xs ys = snd (foldr f (ys,[]) xs) where f x (y:ys,r) = (ys,(x,y):r)
我不明白您如何“取消”堆叠的延续以从顶部的代码块到达底部的代码块。您寻找进行这种转换的方式是什么,为什么会起作用?
我读到富有的hickey说的地方:
"我认为在理论上延续可能是整洁的,但在实践中并非如此"
我不熟悉clojure.
1. clojure有继续吗?
如果不是,你不需要继续吗?我见过很多很好的例子,尤其是这个人.有什么选择?
3.如果是,是否有文件?
Java中是否有良好的延续实现?
如果是这样,那么开销是多少?JVM的设计并没有考虑到这些,对吧?那种反对谷物的是什么?
如何yield return使用Scala continuation 实现C#?我希望能够以Iterator相同的风格编写Scala .这篇Scala新闻帖的评论中有一个刺,但它不起作用(尝试使用Scala 2.8.0测试版).一个相关问题的答案表明这是可能的,但是虽然我已经玩了一段时间的分隔延续,但我似乎无法完全理解如何做到这一点.
我试图找到如何实现call/cc.我发现的最好的是这个Haskell片段:
callCC f = Cont $ \k -> runCont (f (\a -> Cont $ \_ -> k a)) k
Run Code Online (Sandbox Code Playgroud)
虽然这不是那么简单,我想由于Cont和runCont.我也找到了它的功能描述,尽管从未像实际代码那样清晰.
那么它是如何以最简单的形式实现的呢?我用Scheme和Haskell标记它,因为这是我喜欢的两种语言.
continuations ×10
haskell ×4
callcc ×2
scala ×2
scheme ×2
.net ×1
c# ×1
clojure ×1
curry-howard ×1
fold ×1
java ×1
monads ×1
multitasking ×1
queue ×1
scala-2.8 ×1
yield ×1
yield-return ×1