[英]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)
如果有人很好奇,我已經在這里上傳了我的源代碼。
我沒有找對地方(如果您想查看源代碼,顯然avEither正在循環)。 我到達那里的方式是編譯一個二進制文件,然后運行 gdb :
您可以使用 ghc 標志-O0
進行編譯以禁用優化,這可以顯示更多方法名稱。
顯然,上面的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.