如何计算函数被调用的次数,FP方式

时间:2012-03-29 06:26:11

标签: haskell functional-programming

我目前正在使用Haskell进行SICP。练习1.15询问函数被调用的次数。这个想法可能是你应该使用替换方法,但我想知道如何在代码中这样做。

在命令式语言中,可以保留一个全局变量,并在每次调用函数时递增它。但是你会如何在Haskell(或纯粹的功能方式)中实现呢?

2 个答案:

答案 0 :(得分:17)

您可以使用Writer monad来完成此操作,只要对相关函数的所有调用都可以组合成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)

答案 1 :(得分:6)

听起来,无论你是使用功能还是非功能方式,都需要有某种计数器。在Haskell中,您可以使用State Monad来跟踪状态:

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
相关问题