この質問は本質的に 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
て再帰呼び出しをバイパスする必要があります。
非常に奇妙なことは、関数合成のような一般的なサイトに「トレース」呼び出しを挿入すると、プログラムが有限量の出力を発行してからフリーズすることです。無限項展開問題から私が期待するものではありません。(編集1を参照)
誰かが興味を持っている場合は、ここにソースコードをアップロードしました。
編集1
私は正しい場所を探していませんでした (ソースを見たい場合は、明らかにavEitherがループしていたようです)。私がそこにたどり着いた方法は、バイナリをコンパイルして gdb を実行することでした:
- gdb メイン
- r (コードを実行)
- Ctrl+C (割り込み送信) . バックトレースは役に立たないだろうが、できることは当たっている
- s (ステップ) . 次に、Enter キーを押したままにします。多くのメソッド名が飛び交うはずです。そのうちの 1 つが認識されることを願っています。
ghc フラグ-O0
を付けてコンパイルすると、最適化を無効にすることができます。これにより、より多くのメソッド名が明らかになります。
編集3
どうやら、proc x -> do
上記のブロックによってコードがコンビネータを生成し、AVFunctor.arr
リフティング メソッドを呼び出していたようです。トップレベル関数を次のように書き換えると
testAVFunctor = errorArrow "good error" >>>
isError >>> (passError ||| testAVFunctor)
その後、すべて正常に動作します。ガローを学び、使用してみる時が来たと思います(ここバークレーの大学院生による)。
経験からの私の一般的なポイントは、ghci のデバッグがイライラする可能性があるということです。たとえば、ローカル変数として show の引数を作成することはf
できAVFunctor.arr
ましたが、そこから非常に有益なものを取得することはできません。
> :i f
f :: b -> c -- <no location info>
修正後のソースコードはこちら