如何在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

上一篇: How to force evaluation in Haskell?

下一篇: the seq function and strictness