也许是Loeb,为什么&lt; <loop>&gt;有时发生/可以捕获吗?

时间:2015-11-25 21:20:01

标签: haskell exception infinite-loop

我正在玩loeb(https://github.com/quchen/articles/blob/master/loeb-moeb.md):

loeb :: Functor f => f (f a -> a) -> f a
loeb fs = xs where xs = fmap ($ xs) fs

我想写一个函数:

maybeLoeb :: Functor f => f (f a -> a) -> Maybe (f a)

在给定错误输入时失败而不是进入无限循环。

我也很难理解<<loop>>例外的行为。如果可能,我想抓住它。

进入GHCI时:

loeb [(!! 1),(!! 0)] :: [Int]
*** Exception: <<loop>>

但是,在loeb.hs中定义时:

main = print (loeb [(!! 1),(!! 0)] :: [Int])

然后加载到GHCI,:l main我们得到:

*Main> :l loeb
[1 of 1] Compiling Main             ( loeb.hs, interpreted )
Ok, modules loaded: Main.
*Main> main
[

该程序不会终止。

<<loop>>除了可捕捉之外吗?如果是这样,有没有办法让上面的第二个版本抛出异常?

1 个答案:

答案 0 :(得分:3)

存在<<loop>>异常,因为GHC为多线程操作而设计的延迟评估实现,使得单线程运行时系统(RTS)。当多线程RTS需要强制thunk时,它遵循大致如下的过程:

  1. 检查thunk是否已经过评估;如果是这样,请使用已知值并忽略其余部分。

  2. 检查thunk是否标记为正在评估过程中。如果是这样,那么线程就会让任何线程正在处理thunk完成它的工作。回到第0步。

  3. 标记thunk以指示正在评估它。

  4. 评估thunk。

  5. 存储结果并将thunk标记为已评估。

  6. 对于单线程和多线程运行时,使用相同的基本过程,以避免大量的代码重复。但是在单线程运行时,“yield”步骤被<<loop>>异常替换 - 如果程序试图在强制thunk的过程中强制thunk,它肯定会被卡住。肯定没有任何其他线程在强制thunk的中间。

    我不确定是否可以捕获异常,但您肯定不希望依赖来捕获它 - 不同的优化级别或编译器版本可能会在不同的情况下产生异常。程序是否陷入无限循环的问题通常无法回答。作为chi mentions,这被称为停止问题,而Alan Turing的着名证明它无法解决。