问题
Say I have a function concat :: String -> String -> String
. So,
var :: String
var = concat (concat "a" "b") "c") -- "abc"
Now, I have a function which I want to use to calculate how many times concat is called:
func :: (String->String->String) -> Int
So, func var
should return 2.
How should I get this value and at the same time perform the concat?
回答1:
Putting aside that var
has the wrong type, you can't.
Reason 1: You can write exactly the same function as var
without ever calling concat
. Assuming the obvious definition of concat
:
var1 = "a" ++ "b" ++ "c"
or
var2 = "abc"
In fact, the compiler will turn your var
into var2
when you compile with optimizations!
Reason 2: What if the number of calls to concat
depends on the arguments? What should
func f
where f x y = if x == "" then y else (concat x y)
return?
回答2:
The right way to do this is to replace concat :: String -> String -> String
with concatA :: String -> String -> f (String)
, for some appropriate Applicative
f
. For example, you could use Writer
:
concatW :: String -> String -> Writer Int String
concatW s1 s2 = Writer (s1++s2, Sum 1)
Now
concatW s1 s2 >>= concatW s3 >>= concatW s4
Or
(<=) <$> concatW s1 s2 <*> concatW s3 s4
will count things for you.
If you are interested in how many times your function is called for debugging purposes, you may want to use trace
from Debug.Trace
. You may also want to use the profiler and annotate the function as a cost center. You could even use unsafePerformIO
if you're crazy. But these are not things that should generally appear in a released program.
来源:https://stackoverflow.com/questions/28997603/haskell-counting-number-of-function-call