Haskell 梅贝洛布,为什么<&书信电报;环路>&燃气轮机;只是偶尔发生/是否可捕获?

Haskell 梅贝洛布,为什么<&书信电报;环路>&燃气轮机;只是偶尔发生/是否可捕获?,haskell,exception,infinite-loop,Haskell,Exception,Infinite Loop,我在和勒布玩(): 我想写一个函数: maybeLoeb :: Functor f => f (f a -> a) -> Maybe (f a) 当输入错误时,它将失败,而不是进入无限循环 我在理解异常的行为时也遇到了一些困难。如果可能的话,我想抓住它 进入GHCI时: loeb [(!! 1),(!! 0)] :: [Int] *** Exception: <<loop>> 然后用:l main加载到GHCI中,我们得到: *Main> :l

我在和勒布玩():

我想写一个函数:

maybeLoeb :: Functor f => f (f a -> a) -> Maybe (f a)
当输入错误时,它将失败,而不是进入无限循环

我在理解
异常的行为时也遇到了一些困难。如果可能的话,我想抓住它

进入GHCI时:

loeb [(!! 1),(!! 0)] :: [Int]
*** Exception: <<loop>>
然后用
:l main
加载到GHCI中,我们得到:

*Main> :l loeb
[1 of 1] Compiling Main             ( loeb.hs, interpreted )
Ok, modules loaded: Main.
*Main> main
[
程序不会终止

是否可捕获?如果是这样的话,有没有办法让上面的第二个版本抛出异常?

异常之所以存在,是因为GHC实现了惰性评估(专为多线程操作而设计),这使得在使用单线程运行时系统(RTS)时很容易检测到一种非常特殊的无限循环形式。当多线程RTS需要强制thunk时,它会遵循大致如下的过程:

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

  • 检查thunk是否标记为正在评估过程中。如果是这样,线程就会让步,让正在处理该thunk的线程完成其任务。返回到步骤0

  • 标记thunk以指示正在对其进行评估

  • 评估一下这个重击

  • 存储结果并将thunk标记为已评估

  • 相同的基本过程用于单线程和多线程运行时,以避免大量代码重复。但是在单线程运行时,“屈服”步骤被一个
    异常所取代。如果程序在强制执行某个thunk的过程中试图强制执行该thunk,那么它肯定会被卡住。在强制thunk的过程中肯定没有其他线程。


    我不确定是否可以捕获异常,但您肯定永远不想依赖于捕获它。不同的优化级别或编译器版本可能会在不同的情况下生成异常。您的程序是否陷入无限循环的问题通常无法回答。这就是所谓的停顿问题,艾伦·图灵(Alan Turing)著名地证明了这是无法解决的。

    我担心您正在试图解决停顿问题。您可能能够捕获(在
    IO
    monad中),但在更复杂的情况下,GHC实际上会循环,而不是生成可捕获的异常。您的函数将任何
    Functor f=>f(f a->f)
    作为输入,不知道其他任何信息,您知道,您可以使用该值对其执行的所有操作都是
    fmap
    ——为某些
    b
    生成其他
    fb
    。这绝不可能是任何c的
    可能(fc)
    形式。没有任何函数可以将一般函子转换为
    可能
    任何东西-使用
    函子
    根本无法实现这一点。您可能会更幸运地使用
    可遍历的f=>f(fa->maybea)->maybea(fa)
    ?我不确定。
    main = print (loeb [(!! 1),(!! 0)] :: [Int])
    
    *Main> :l loeb
    [1 of 1] Compiling Main             ( loeb.hs, interpreted )
    Ok, modules loaded: Main.
    *Main> main
    [