哈斯克尔计算函数调用的数量



>假设我有一个函数concat :: String -> String -> String。所以

var :: String
var = concat (concat "a" "b") "c")  -- "abc"

现在,我有一个函数,我想用它来计算调用 concat 的次数:

func :: (String->String->String) -> Int

因此,func var应返回 2。

我应该如何获取此值并同时执行连接?

撇开var的类型错误不谈,你不能。

原因1:你可以编写与var完全相同的函数,而无需调用concat。假设concat的明显定义:

var1 = "a" ++ "b" ++ "c"

var2 = "abc"
事实上,当您

使用优化进行编译时,编译器会将您的var变成var2

原因 2:如果对concat的调用次数取决于参数怎么办?应该做什么

func f 
  where f x y = if x == "" then y else (concat x y)

返回?

正确的方法是将concat :: String -> String -> String替换为 concatA :: String -> String -> f (String) ,以获得一些适当的Applicative f。例如,您可以使用Writer

concatW :: String -> String -> Writer Int String
concatW s1 s2 = Writer (s1++s2, Sum 1)

现在

concatW s1 s2 >>= concatW s3 >>= concatW s4

(<=) <$> concatW s1 s2 <*> concatW s3 s4

会为你计算事情。


如果您对出于调试目的调用函数的次数感兴趣,则可能需要使用 Debug.Trace 中的trace。您可能还希望使用探查器并将函数注释为成本中心。如果你疯了,你甚至可以使用unsafePerformIO。但这些通常不应该出现在已发布的程序中。

最新更新