Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将Scheme call/cc转换为Haskell callCC 让我们考虑一下另一个非终止折叠: (呼叫/抄送(lambda(折叠) (溪流褶皱) (lambda(附件五) (如果(_Haskell_Scheme_Continuations - Fatal编程技术网

将Scheme call/cc转换为Haskell callCC 让我们考虑一下另一个非终止折叠: (呼叫/抄送(lambda(折叠) (溪流褶皱) (lambda(附件五) (如果(

将Scheme call/cc转换为Haskell callCC 让我们考虑一下另一个非终止折叠: (呼叫/抄送(lambda(折叠) (溪流褶皱) (lambda(附件五) (如果(,haskell,scheme,continuations,Haskell,Scheme,Continuations,上述代码的Haskell等价物是 callCC$\folded->foldl(\acc v->如果v

上述代码的Haskell等价物是

callCC$\folded->foldl(\acc v->如果v<5那么v:acc else folded acc)[0..]

这段代码没有编译,并且抱怨无法在表达式中构造无限类型。我已经知道如何在Y combinator这样的情况下消除这种错误,但是相同的方法在这里似乎不起作用。对于这种情况,什么是正确的方法?

是的;作为j。亚伯拉罕说

import Control.Monad.Trans.Cont
import Control.Monad

bar :: Cont r [Int]
bar = callCC $ \folded ->
    foldM (\acc v -> do
        when (v >= 5) $ folded acc
        return $ v : acc) [] [0..]

thing = runCont bar id

工作。

首先,正如前面所解释的,Scheme call/cc和Haskell callCC有些不同 在页面上

主要问题是您可能根本不需要call/cc——即使在Scheme中也是如此。您的打破循环的示例使用异常实现得更好——从效率的角度来看更好(不需要捕获您无论如何都不会使用的延续),并且在概念上更好。如果任务是中止当前的延续,那么有一些工具正是用于此目的的。R7RS已经认识到这一点,并引入了例外情况。要在Haskell中使用异常,请使用Error或monad。例如,在您的代码中

baz :: Either [Int] [Int]
baz = foldM (\acc v -> do
        when (v >= 5) $ Left acc
        return $ v : acc) [] [0..]

thing1 = either id id baz
操作员呼叫/cc是在缺乏控制操作员经验的情况下引入该方案的。现在我们有了很多经验,call/cc的许多严重缺点已经暴露出来。如果您对更多细节感兴趣,下面的页面将详细介绍call/cc的问题。

使用
foldM
而不是
foldl
。这里有一个
v:acc
折叠的acc
不返回相同的类型。谢谢你的回答。它在这种情况下有效,但似乎相当专业化。是否有一个通用的方法来翻译方案代码与呼叫/ CC到Haskell或我应该总是考虑每个案件通过查看类型签名?