Как подсчитать количество раз, когда была вызвана функция, способ FP
В настоящее время я работаю через SICP с Haskell. Упражнение 1.15 спрашивает, сколько раз вызывается функция. Идея, вероятно, в том, что вы должны использовать метод подстановки, но я хотел бы знать, как это сделать в коде.
На императивном языке можно хранить глобальную переменную и увеличивать ее каждый раз, когда вызывается функция. Но как бы вы это сделали в Haskell (или чисто функциональном)?
Ответы
Ответ 1
Вы можете использовать монаду 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)
Ответ 2
Мне кажется, что вам нужно иметь какой-то счетчик, независимо от того, идете ли вы с функциональным или нефункциональным способом. В 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
обратно. Если вы запустите этот script, он должен распечатать
result: 9
# of calls: 3