如何在Haskell中强制进行评估?
我对Haskell相对比较陌生,我正试着学习如何使用符号按顺序执行不同的动作。 特别是,我正在编写一个程序来对一个算法(一个函数)进行基准测试,
foo :: [String] -> [String]
为此我想写一个函数
import System.CPUTime
benchmark :: [String] -> IO Integer
benchmark inputList = do
start <- getCPUTime
let r = foo inputList
end <- getCPUTime
return (end - start) -- Possible conversion needed.
最后一行可能需要转换(例如毫秒),但这不是这个问题的主题。
这是衡量在某些参数inputList上计算函数foo所需时间的正确方法吗?
换句话说,在执行end <- getCPUTime
之前,表达式foo inputList
会被完全减少? 或将r
仅结合形实转换foo inputList
?
更一般的情况是,如何确保在执行某个操作之前对表达式进行了全面评估?
这个问题在几个月前被程序员问过(见这里),并且在那里有一个被接受的答案,但是由于它属于堆栈溢出,因此它已被关闭为脱离主题。 这个问题不能转移到堆栈溢出,因为它超过了60天。 所以,根据协调人的协议,我在这里重新发布这个问题,并自己发布接受的问题,因为我认为它包含一些有用的信息。
最初由用户ysdx给程序员提供的答案:
事实上,你的版本不会测试你的算法。 因为r
不被使用,所以根本不会被评估。
你应该可以用DeepSeq完成它:
benchmark :: [String] -> IO Integer
benchmark inputList = do
start <- getCPUTime
let r = foo inputList
end <- r `deepseq` getCPUTime
return (end - start)
( a `deepseq` b
)是一些“魔力”表达这迫使的完整/递归计算a
返回之前b
。
我会使用语言扩展-XBangPatterns,在这种情况下我发现它很有表现力。 所以你必须说“ let !r = foo inputList
”,如下所示:
{-# LANGUAGE BangPatterns #-}
import System.CPUTime
benchmark :: [String] -> IO Integer
benchmark inputList = do
start <- getCPUTime
let !r = foo inputList
end <- getCPUTime
return (end - start)
链接地址: http://www.djcxy.com/p/42969.html