現在、私は現在、HaskellでSICPを使っています。エクササイズ1.15では、関数が何回呼び出されたかを尋ねます。考え方はおそらく置換メソッドを使うべきですが、私はコードでそれを行う方法を知りたいと思います。ファンクションが呼び出された回数、FP方法
命令型言語では、グローバル変数を保持し、関数が呼び出されるたびにインクリメントすることができます。しかし、あなたはハスケル(または純粋な機能的な方法)でそれについてどうやって行くのですか?
現在、私は現在、HaskellでSICPを使っています。エクササイズ1.15では、関数が何回呼び出されたかを尋ねます。考え方はおそらく置換メソッドを使うべきですが、私はコードでそれを行う方法を知りたいと思います。ファンクションが呼び出された回数、FP方法
命令型言語では、グローバル変数を保持し、関数が呼び出されるたびにインクリメントすることができます。しかし、あなたはハスケル(または純粋な機能的な方法)でそれについてどうやって行くのですか?
を印刷する必要がありますが、これを達成するためにWriter
モナドを使用することができ、問題の関数の呼び出しのすべてがdo
ブロックにまとめることができることを提供する:
import Control.Monad.Writer
myFunc :: Int -> Int -> Writer (Sum Int) Int
myFunc a b = tell (Sum 1) >> return (a + b)
callMyFunc :: ((Int, Int, Int), Sum Int)
callMyFunc = runWriter $ do a <- myFunc 2 3
b <- myFunc 8 7
c <- myFunc 3 5
return (a, b, c)
main = putStrLn $
"myFunc was called "
++ show (getSum $ snd callMyFunc)
++ " times and produced "
++ show (fst callMyFunc)
出力
:
myFunc was called 3 times and produced (5,15,8)
機能的かどうかに関係なく、何らかのカウンターが必要なように聞こえます。 Haskellでは、あなたは状態を追跡するためにState
モナドを使用することができます。
import Control.Monad.State
someFunc x = do
num <- get
put (num + 1)
return $ x * x
runSomeFuncs = do
someFunc 1
someFunc 2
someFunc 3
main = do
let (res, state) = runState runSomeFuncs 0
putStrLn ("result: " ++ (show res))
putStrLn ("# of calls: " ++ show state)
、あなたはsomeFunc
が呼ばれました回数を記録しておきたいので、我々は国家としての整数を渡し、インクリメント
num <- get
put (num + 1)
をし、その後1とバックput
それをすることによって、それをインクリメント:整数たびは、関数が使用することによって呼び出されます。このスクリプトを実行すると、それは
result: 9
# of calls: 3
'get'tingと' put'の代わりに 'modify(+ 1)'を実行してください。 – dave4420
ここで 'State'を使うと、カウンタにも依存することができ、不必要なデータ依存性(例えば、並列性を制限する)を作成します。代わりに 'Writer'を' Monoid'として 'Sum Int'を使って、そして' tell(Sum 1) 'を使ってカウンタを増やすことができます。これは加算の結合性をうまく利用し、同じWriter計算を複数回呼び出すときにもCSEを可能にします。 – Peaker
@Peakerそれを展開して答えとして投稿してください。 – dave4420
た場合にのみ、デバッグのためには、あなたは 'Debug.Trace'の' trace'機能を使用することができます。参照透過性が損なわれますが、デバッグや探索をしている場合はそれが問題ありません。 – GManNickG
Ahem、私はSICPが実際にカウントが0か1のどちらかであると考えていると思います - ジストは「評価された関数かどうか」です。関数が呼び出された回数を数える関数的な方法はありません。以下の答えは、良いモナド "ソリューション"を提供しますが、それぞれのモナド内でカウントされる関数に依存しています。これは重要なニット・ピックです。彼らは一般的な機能を数えません。 –