2012-03-29 13 views
14

現在、私は現在、HaskellでSICPを使っています。エクササイズ1.15では、関数が何回呼び出されたかを尋ねます。考え方はおそらく置換メソッドを使うべきですが、私はコードでそれを行う方法を知りたいと思います。ファンクションが呼び出された回数、FP方法

命令型言語では、グローバル変数を保持し、関数が呼び出されるたびにインクリメントすることができます。しかし、あなたはハスケル(または純粋な機能的な方法)でそれについてどうやって行くのですか?

+0

た場合にのみ、デバッグのためには、あなたは 'Debug.Trace'の' trace'機能を使用することができます。参照透過性が損なわれますが、デバッグや探索をしている場合はそれが問題ありません。 – GManNickG

+3

Ahem、私はSICPが実際にカウントが0か1のどちらかであると考えていると思います - ジストは「評価された関数かどうか」です。関数が呼び出された回数を数える関数的な方法はありません。以下の答えは、良いモナド "ソリューション"を提供しますが、それぞれのモナド内でカウントされる関数に依存しています。これは重要なニット・ピックです。彼らは一般的な機能を数えません。 –

答えて

18

を印刷する必要がありますが、これを達成するために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) 
6

機能的かどうかに関係なく、何らかのカウンターが必要なように聞こえます。 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 
+14

'get'tingと' put'の代わりに 'modify(+ 1)'を実行してください。 – dave4420

+7

ここで 'State'を使うと、カウンタにも依存することができ、不必要なデータ依存性(例えば、並列性を制限する)を作成します。代わりに 'Writer'を' Monoid'として 'Sum Int'を使って、そして' tell(Sum 1) 'を使ってカウンタを増やすことができます。これは加算の結合性をうまく利用し、同じWriter計算を複数回呼び出すときにもCSEを可能にします。 – Peaker

+0

@Peakerそれを展開して答えとして投稿してください。 – dave4420

関連する問題