簡體   English   中英

Haskell 中的無限遞歸

[英]Infinite recursion in Haskell

這個問題本質上是使用 GHCi 調試 Haskell 程序中的無限循環的副本 那里的作者手動解決了它,但我想知道其他解決方案

(我的特殊問題)

我有一個包含遞歸調用的箭頭代碼,

testAVFunctor = proc x -> do
    y <- errorArrow "good error" -< x
    z <- isError -< y
    (passError ||| testAVFunctor) -< trace "value of z" z

errorArrow應該使遞歸 testAVFunctor 不執行,因為這將導致 isError 返回一個Left (AVError "good error") ,它應該依次選擇passError路由並繞過遞歸調用。

非常奇怪的是,在 function 組合等熱門站點插入“跟蹤”調用會導致程序發出有限數量的 output,然后凍結。 不是我對無限項擴展問題的期望。 (見編輯1)

如果有人很好奇,我已經在這里上傳了我的源代碼。

編輯 1

我沒有找對地方(如果您想查看源代碼,顯然avEither正在循環)。 我到達那里的方式是編譯一個二進制文件,然后運行 gdb

  • gdb 主
  • r (運行代碼)
  • Ctrl+C (發送中斷) 回溯將是無用的,但你能做的,是命中
  • s (步驟) 然后,按住回車鍵; 您應該會看到很多方法名稱飛過。 希望其中一個能夠被識別。

您可以使用 ghc 標志-O0進行編譯以禁用優化,這可以顯示更多方法名稱。

編輯 3

顯然,上面的proc x -> do塊導致代碼生成組合器,這些組合器正在調用要調用的AVFunctor.arr提升方法——其中一定有違反惰性的東西。 如果我將頂層 function 重寫為

testAVFunctor = errorArrow "good error" >>>
    isError >>> (passError ||| testAVFunctor)

然后一切正常。 我想是時候嘗試學習和使用garrows (伯克利的一名研究生)。

我從經驗中得出的一般結論是 ghci 調試可能會令人沮喪。 例如,我設法使AVFunctor.arr的參數f顯示為局部變量,但我無法從中獲得任何非常有用的信息:

> :i f
f :: b -> c     -- <no location info>

修改后的源代碼在這里

請記住, (|||)的含義取決於箭頭,而testAVFunctor是箭頭的無限 object:

testAVFunctor = proc x -> do
    ...
    (passError ||| proc x -> do
                       ...
                       (passError ||| proc x -> ...) -< trace "value of z" z)
        -< trace "value of z" z

我不確定你是否意識到這一點。 檢查(|||)的定義(或者如果沒有,則left ),看看它是否可以處理無限項。 還要檢查(>>>) (呃,我認為現代版本中的(.) )。 確保組合子不是嚴格的,因為那樣無限項會發散。 這可能涉及使用~使模式更懶惰(在使用箭頭時我不得不這樣做很多)。 您看到的行為可能是由於其中一個組合器過於嚴格造成的,因此它評估“足夠遠”以給出一些 output 但后來卡住了。

祝你好運。 您已深入了解 Haskell 的精妙之處。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM