我正在玩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>>
除了可捕捉之外吗?如果是这样,有没有办法让上面的第二个版本抛出异常?
答案 0 :(得分:3)
存在<<loop>>
异常,因为GHC为多线程操作而设计的延迟评估实现,使得单线程运行时系统(RTS)。当多线程RTS需要强制thunk时,它遵循大致如下的过程:
检查thunk是否已经过评估;如果是这样,请使用已知值并忽略其余部分。
检查thunk是否标记为正在评估过程中。如果是这样,那么线程就会让任何线程正在处理thunk完成它的工作。回到第0步。
标记thunk以指示正在评估它。
评估thunk。
存储结果并将thunk标记为已评估。
对于单线程和多线程运行时,使用相同的基本过程,以避免大量的代码重复。但是在单线程运行时,“yield”步骤被<<loop>>
异常替换 - 如果程序试图在强制thunk的过程中强制thunk,它肯定会被卡住。肯定没有任何其他线程在强制thunk的中间。
我不确定是否可以捕获异常,但您肯定不希望依赖来捕获它 - 不同的优化级别或编译器版本可能会在不同的情况下产生异常。程序是否陷入无限循环的问题通常无法回答。作为chi mentions,这被称为停止问题,而Alan Turing的着名证明它无法解决。