ddk*_*ddk 14 haskell functional-programming
我目前正在与Haskell 一起完成SICP.练习1.15询问函数被调用的次数.这个想法可能是你应该使用替换方法,但我想知道如何在代码中这样做.
在命令式语言中,可以保留全局变量,并在每次调用函数时递增它.但是你会如何在Haskell(或纯粹的功能方式)中实现呢?
bit*_*ket 17
您可以使用Writermonad来完成此操作,前提是所有对相关函数的调用可以组合成一个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)
Run Code Online (Sandbox Code Playgroud)
哪个输出:
myFunc was called 3 times and produced (5,15,8)
Run Code Online (Sandbox Code Playgroud)
对我来说,无论你是使用功能还是非功能方式,都需要有一些计数器.在Haskell中,您可以使用StateMonad来跟踪状态:
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)
Run Code Online (Sandbox Code Playgroud)
在这里,你想跟踪someFunc被调用的次数,所以我们传递一个整数作为状态,并在每次调用函数时使用以下函数递增整数:
num <- get
put (num + 1)
Run Code Online (Sandbox Code Playgroud)
然后将它递增1并put返回.如果您运行此脚本,则应该打印
result: 9
# of calls: 3
Run Code Online (Sandbox Code Playgroud)