我目前正在使用Haskell进行SICP。练习1.15询问函数被调用的次数。这个想法可能是你应该使用替换方法,但我想知道如何在代码中这样做。
在命令式语言中,可以保留一个全局变量,并在每次调用函数时递增它。但是你会如何在Haskell(或纯粹的功能方式)中实现呢?
答案 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