Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to count the number of times a function was called, the FP way

I am currently working through SICP with Haskell. Exercise 1.15 asks how many times a function is called. The idea is probably that you should use the substitution method, but I would like to know how to do so in code.

In an imperative language one can keep a global variable and increment it every time the function is called. But how would you go about it in Haskell (or the pure functional way)?

like image 713
ddk Avatar asked Mar 29 '12 06:03

ddk


People also ask

How do you find out how many times a function is called?

To count how many times a function has been called, declare a count variable outside of the function, setting it to 0 . Inside of the body of the function reassign the variable incrementing it by 1 . The count variable will store the number of function invocations. Copied!

What is used to track how many times a function has been called in angular?

count() The console. count() method logs the number of times that this particular call to count() has been called.

How do you count how many times a function has been called Python?

To use it, simply decorate a function. You can then check how many times that function has been run by examining the "count" attribute.


2 Answers

You can use the Writer monad to accomplish this, provided that all of the calls to the function in question can be grouped together into a do block:

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)

Which outputs:

myFunc was called 3 times and produced (5,15,8)
like image 148
bitbucket Avatar answered Oct 19 '22 04:10

bitbucket


It sounds to me like you need to have some kind of counter regardless of whether you go with a functional or a non-functional way. In Haskell, you could use the State Monad to keep track of the 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)

Here, you want to keep track of how many times someFunc got called, so we pass an integer in as the state and increment the integer every time the function gets called by using:

num <- get
put (num + 1)

and then increment it by 1 and put it back. If you run this script, it should print

result: 9
# of calls: 3
like image 7
Vlad the Impala Avatar answered Oct 19 '22 03:10

Vlad the Impala