Haskell程式中止與“迴圈”,但我認為它不應該
我有這個Haskell程式碼,當用GHC編譯並執行時,中止檢測到一個迴圈.
data Foo = Foo () deriving (Eq,Show) type Foop = Foo -> ((),Foo) noOp :: Foop noOp st = ((),st) someOp :: Foop someOp st@(Foo x) = ((),st) (<+>) :: Foop -> Foop -> Foop (<+>) f g st = let ((_,st'),(_,st'')) = ((f st),(g st')) in ((),st'') main = print $(noOp <+> someOp) $Foo ()
我認為不應該,這裡有一些修改.他們中的每一個使迴圈消失:
>更改資料Foo到newtype Foo
> change(noOp〜someOp)到(someOp&no; noOp)
刪除解構@(Foo x)
這是GHC中的錯誤還是我對評估過程缺乏瞭解?
模式匹配(_,_)要求(f st,g st’)的WHNF.簡單.
模式匹配(_,(_,_))需要gst’的WHNF.這是問題,因為g是嚴格的,因此它首先需要在WHNF中.執行時在模式((_,st’),(_,_))中查詢st’,所以在實際上可以遍歷到st之前,需要兩個元組的WHNF.因為g是嚴格的,這首先需要st …等等.
如果您將g的結果與懶惰的無可辯駁的模式相匹配
(<+>) f g st = let ((_,st'), ~(_,st'')) = (f st, g st') in ((),st'')
那麼這個問題就消失了,因為這樣被評估:
模式匹配(_,_)要求(f st,g st’)的WHNF.簡單.
模式匹配(_,〜(_,_))暫時不再需要了.
模式匹配((_,st’),〜(_,_))要求fst的WHNF.幸運的是,我們可以實現這一點,因為st不依賴於模式.
>現在我們已經滿足了模式匹配,執行時可以在((),st“)中進行.只有在這一點上,這是無可辯駁的模式〜(_,st“)被強制,但現在這不是一個問題,因為st’在這裡可用,所以這只是計算一次的問題.
您嘗試過的修復程式都使g非嚴格:
remove the deconstruction@(Foo _)
沒有了,g並不需要看它的引數來構造結果框架,也就是說,元組匹配(_,st“)可以成功,而不必先要求st’的WHNF.
changedata Foo
tonewtype Foo
這具有Foo建構函式在執行時並不存在的效果,所以模式st @(Foo _)將不會強制執行.
changenoOp <+> someOp
tosomeOp <+> noOp
正如我所說,迴圈只是因為g是嚴格的.如果你把f放在自己的位置,那是不嚴格的,那沒有問題.
程式碼日誌版權宣告:
翻譯自:http://stackoverflow.com/questions/37846161/haskell-program-aborts-with-loop-but-i-think-it-shouldnt