简体   繁体   English

如何在Haskell中强制评估?

[英]How to force evaluation in Haskell?

I am relatively new to Haskell and I am trying to learn how different actions can be executed in sequence using the do notation. 我对Haskell相对较新,我正在尝试学习如何使用符号按顺序执行不同的操作。 In particular, I am writing a program to benchmark an algorithm (a function) 特别是,我正在编写一个程序来对算法进行基准测试(一个函数)

foo :: [String] -> [String]

To this purpose I would like to write a function like 为此,我想写一个像这样的函数

import System.CPUTime

benchmark :: [String] -> IO Integer
benchmark inputList = do
                         start <- getCPUTime
                         let r = foo inputList
                         end <- getCPUTime
                         return (end - start) -- Possible conversion needed.

The last line might need a conversion (eg to milliseconds) but this is not the topic of this question. 最后一行可能需要转换(例如,毫秒),但这不是这个问题的主题。

Is this the correct way to measure the time needed to compute function foo on some argument inputList? 这是衡量在某个参数inputList上计算函数foo所需时间的正确方法吗?

In other words, will the expression foo inputList be completely reduced before the action end <- getCPUTime is executed? 换句话说,在动作end <- getCPUTime执行之前,表达式foo inputList会完全减少? Or will r only be bound to the thunk foo inputList ? 或者r只能绑定到thunk foo inputList

More in general, how can I ensure that an expression is completely evaluated before some action is executed? 更一般地说,如何在执行某些操作之前确保完全评估表达式?


This question was asked a few months ago on programmers (see here ) and had an accepted answer there but it has been closed as off-topic because it belongs on stack overflow. 这个问题几个月前被问到程序员(见这里 )并在那里得到了一个可接受的答案,但它已被关闭为主题,因为它属于堆栈溢出。 The question could not be moved to stack overflow because it is older than 60 days. 问题无法移动到堆栈溢出,因为它超过60天。 So, in agreement with the moderators, I am reposting the question here and posting the accepted question myself because I think it contains some useful information. 因此,与主持人达成一致意见,我在此处重新提出问题并自行发布已接受的问题,因为我认为它包含一些有用的信息。

Answer originally given by user ysdx on programmers : 最初由用户ysdx给出的程序员答案:

Indeed you version will not benchmark your algorithm. 实际上,您的版本不会对您的算法进 As r is not used it will not be evaluated at all. 由于r未被使用,因此根本不进行评估。

You should be able to do it with DeepSeq : 您应该能够使用DeepSeq

 benchmark :: [String] -> IO Integer benchmark inputList = do start <- getCPUTime let r = foo inputList end <- r `deepseq` getCPUTime return (end - start) 

( a `deepseq` b ) is some "magic" expression which forces the complete/recursive evaluation of a before returning b . a `deepseq` b )是一些“魔力”表达这迫使的完整/递归计算a返回之前b

I would use the language extension -XBangPatterns , I find that quite expressive in such situations. 我会使用语言扩展-XBangPatterns ,我觉得在这种情况下很有表现力。 So you would have to say " let !r = foo inputList " as in: 所以你必须说“ 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM