11

どうしていいかわからない問題があります。誰かが特定の問題について私を助けてくれるかどうか尋ねようとしていましたが、より一般的な質問をすることができ、結果としてより一般的な理解が得られることを願っています. うまくいけば。だからここに行きます:

たとえば、スペース リークなどの明らかな問題が発生するため、プログラムがあまりにも怠惰な場合は、通常は明らかです。逆の問題があります: 私のプログラムは厳しすぎます。私は結び目を作ろうと いますが、私がやろうとしている特定のことが、私が必要とする怠惰をどうにかして打ち負かすことがわかりました. 私の一般的な質問は、不要な厳密さをどのようにデバッグするのですか?


完全を期すために、ここに私の具体的なケースを示します。私はRWS、ライター コンポーネントがマップにデータを入力し、リーダー コンポーネントがそのマップの最終状態を観察します。マップへの入力が完了するまで、このマップに対して厳密なことを行うことはできません。次のように、マップ内の値を検索することは問題ないようです。

do
  m <- ask
  val <- m ! key
  doSomething val -- etc.

しかし、 の(!)使用errorに失敗します。代わりに、モナドの の使用に失敗することを好みfailます。だから私は次のようなことをしたいと思います:

do
  m <- ask
  maybe
    (fail "oh noes")
    (doSomething)
    (lookup key m)

これにより、私のプログラム<<loop>>は理解できません。これがを使用するよりも厳密であるようには思え(!)ませんが、明らかに私は間違っています...

4

1 に答える 1

10

最初の例は、マップで厳密です。以下は を検索してprint "1"実行し、プログラムは実際に 1 を出力します。もちろん、これには を評価する必要がありmます。

main = do let m = Map.fromList [(1, print "1")]
          val <- m ! 1
          return val

おそらく、マップのみを読み取るものを作成するつもりでした。valは case 式で使用されていないため、以下は厳密ではありません。

main = do let m = Map.fromList [(1, print "1")]
          let val = m ! 1
          return val

lookup2 番目の例は、do ブロックの実行を終了する方法を決定するために、成功したかどうかをチェックするため、厳密です。それには地図を読む必要があります。それは以下と同等です:

do m <- ask
   case lookup key m of
     Nothing -> fail "oh noes"
     Just x  -> doSomething x 

厳密性の問題のデバッグ

+評価は、ケース式または整数などの組み込み演算子によって常に強制されます。値が使用可能になる前に値が強制されたためにプログラムが失敗していると思われる場合は、どの値が強制されているのか、どこで強制されているのかを調べる必要があります。

どの値が強制されましたか?

この種のバグでは、プログラムは自身の評価結果に依存する式を評価しようとします。traceどの式が評価されているかを追跡するために使用できます。この問題では、 の値mが強制されているように見えるため、trace評価される直前にメッセージを出力するために使用します。

do m1 <- ask
   let m = trace "Using m" m1
   ...

"Using m" がプログラムからの最後の出力 ( の前<<loop>>) である場合、バグに近づいています。出力にない場合mは評価されていないため、問題は別の場所にあります。出力でこの行に何かが続く場合、プログラムは実行を継続し、後でエラーが発生したため、問題は別の場所にあるはずです。

どこに強要された?

これは、評価が停止する前に少なくともここまで到達したことを示しています。しかし、それはどこまで行きましたか?問題が実際に発生したのはずっと後のことですか? それを確認するには、trace後で評価されるものに a を付けてみてください。mどのブランチが実行されるかを決定するために が評価されることがわかっているので、それらのポイントmaybeに置くことができます。trace

do m1 <- ask
   let m = trace "Using m" m1
   maybe (trace "Used m" $ fail "oh noes")
         (\x -> trace "Used m" $ doSomething x)
         (lookup key m)

出力に "Using m" の後に "Used m" が表示される場合、m終了の評価が行われ、プログラムが続行されたことがわかります。"Using m" のみが表示される場合、プログラムはこれらのポイントの間で停止しています。この特定のケースでは、 " maybeUsed m" は表示されません。m<<loop>>

于 2012-07-07T06:26:19.900 に答える