Haskellのデバッグテクニックを簡単に説明します
3570 ワード
穴に入るのは1ヶ月も違わないで、ずっとHaskellの中でこの1回をデバッグすることに関心を持ったことがなくて、1つは複雑なプログラムを書いていないで、大多数はすべてコンパイルの間違いで、調整してコンパイルしたことがあって終わりました.二つ目は手元のいくつかの本で、
だから今まで出会ったランタイムエラーは、私はBVM(Brain Virtual Machine,)を採用しています.を選択して検索します.
もちろん、BVMは簡単なプログラムにも適用されます.最近簡単なCompilerを書いて、LLVM IRを生成する時1つのBugに出会って、すべての
私がBVMを使って脳の中で流れを演じた数百万回も特ニャンがこのバグを見つけられなかったとき.私はすっかり感心して、おとなしくHaskellのデバッグのテクニックを勉強しました.
コマンドプログラミングでは、適切な場所に
The answer is YES!
trace
GHCは実はかなりのdebug方法を内蔵して、具体的にはここを見て、ここで最も簡単で最も実用的な方法を話します——
このような関数があるとします.
だから不思議なことに、1つの文字列sと1つの整数nを受け入れて、1つのs[0..
実行すると、次のような出力が表示されます.
見慣れた
何だ?私を信じて、私が初めて見たとき、あなたと同じ感じでした.
人の話で言えば、Stringパラメータは、あなたが印刷するもので、中にはあなたが必要とするcontext infoの文字列が含まれていますが、aは一般的に式、あるいは関数で、ここにaが実行した結果を表す任意のタイプで書くことができます.
したがって、プログラムの実行については、
デバッグdo block
実際、Haskellプログラムの多くの複雑な論理はmonadicの形式で書かれています.よく知られているdo blockですが、次の例を見てみましょう.
今回私たちが操作する文字列は、パラメータを介して渡されたのではなく、wrapが
多くのHaskellの関数のように、traceにもmonadicの双子の兄弟がいます.
簡単に一言追加するだけです
プログラムを実行し、出力:
コマンド言語のように間違った場所でロゴを打ってdebugを手伝うことに成功しましたそれはそう簡単には理解できませんが.
注意すべき点は、
もっと見たい?私の知っていることに注目することができます
Learn you a haskell
、Real World Haskell
そしてThe craft of functional Programming
はHaskellデバッグのテクニックについて話していません.もちろん、これもHaskellの比較的高い寒さの特質に合っています.いずれもputStrLn
という関数を紹介しますが、この関数はIO Monadと一緒に使わなければなりません.便利ではありません.使う場所が多ければ非常に美しくありません.だから今まで出会ったランタイムエラーは、私はBVM(Brain Virtual Machine,)を採用しています.を選択して検索します.
もちろん、BVMは簡単なプログラムにも適用されます.最近簡単なCompilerを書いて、LLVM IRを生成する時1つのBugに出会って、すべての
Variable
タイプのデータに対してすべて失敗して、1つの
を返して、load
を試してみる時1つのcasting error
を報告します.私がBVMを使って脳の中で流れを演じた数百万回も特ニャンがこのバグを見つけられなかったとき.私はすっかり感心して、おとなしくHaskellのデバッグのテクニックを勉強しました.
コマンドプログラミングでは、適切な場所に
print
文を挿入してcontext infoを印刷することが基本です.ではハスカルで優雅に実現できるのでしょうか?The answer is YES!
trace
GHCは実はかなりのdebug方法を内蔵して、具体的にはここを見て、ここで最も簡単で最も実用的な方法を話します——
Debug.Trace
traceを使用するのは簡単で、ファイルの先頭import Debug.Trace
だけでいいです.このような関数があるとします.
subStringToIndex :: String -> Int -> String
subStringToIndex s n = take n s
だから不思議なことに、1つの文字列sと1つの整数nを受け入れて、1つのs[0..
subStringToIndex :: String -> Int -> String
subStringToIndex s n = trace ("para s is " ++ show s) take n s
実行すると、次のような出力が表示されます.
para s is "abcde"
ab
見慣れた
printf
を再見したような気がしますか?濃厚な親切な風が店を開いた.traceも関数であり、非常に簡単に使用されていることは、そのプロトタイプの宣言から見ることができます.trace :: String -> a -> a
trace
の役割公式ドキュメントでは、文字列と任意のタイプのaのパラメータを受け入れ、この文字列を印刷し、aを返します.何だ?私を信じて、私が初めて見たとき、あなたと同じ感じでした.
人の話で言えば、Stringパラメータは、あなたが印刷するもので、中にはあなたが必要とするcontext infoの文字列が含まれていますが、aは一般的に式、あるいは関数で、ここにaが実行した結果を表す任意のタイプで書くことができます.
trace
は文字列を印刷し、2番目のパラメータを結果として返します.したがって、プログラムの実行については、
trace "message : " (f x)
と直接f x
の効果は同じであり、trace
は実行前に関連情報を印刷するだけである.デバッグdo block
実際、Haskellプログラムの多くの複雑な論理はmonadicの形式で書かれています.よく知られているdo blockですが、次の例を見てみましょう.
monadicSubStringToIndex :: Int -> State String String
monadicSubStringToIndex n = do
s1
今回私たちが操作する文字列は、パラメータを介して渡されたのではなく、wrapが
State Monad
にある文字列です.もしこの時私たちがdebugmonadicSubStringToIndex
に来たらどうすればいいですか?do blockの文ブロックは、現在のmonadを入力として受け入れ、monadを出力しなければならないことを知っています.上記のtrace
は、ここでは適用できないことは明らかである.多くのHaskellの関数のように、traceにもmonadicの双子の兄弟がいます.
traceM
これはすべてを簡単にします.簡単に一言追加するだけです
monadicSubStringToIndex :: Int -> State String ()
monadicSubStringToIndex n = do
s take n s)
main :: IO ()
main = putStrLn $ snd $ runState (monadicSubStringToIndex 2) "abcde"
プログラムを実行し、出力:
original string is "abcde"
ab
コマンド言語のように間違った場所でロゴを打ってdebugを手伝うことに成功しましたそれはそう簡単には理解できませんが.
traceM
の定義は次のとおりです.traceM :: Monad m => String -> m ()
trace
と比較すると、traceMには印刷する文字列というパラメータが1つしかなく、任意のタイプのmonadを返します.しかし、任意のmonadicの関数には、現在のmonadである隠し入力パラメータがあることに注意してください.したがって、構造上、trace
とtraceM
は一致する.ここからも一般的なHaskellプログラミングは関数呼び出しを主線とし,monadicの書き方はmonadの伝達を主線としていることがわかる.注意すべき点は、
trace
でもtraceM
でも副作用があることです.使用する場所はpure
ではなく、referentially transparent
ではありません.簡単に言えば、Haskell言語の特性を満たすfeatureではないので、デバッグ時にのみ使用できます.もっと見たい?私の知っていることに注目することができます