2013-01-04 52 views
19

我對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只會綁定到thunk foo inputList

更一般來說,如何確保在執行某個操作之前完全評估表達式?


這個問題被問得幾個月前程序員(見here),並已被接受的答案有,但因爲它屬於對堆棧溢出它已關閉的題外話。這個問題不能轉移到堆棧溢出,因爲它超過了60天。所以,根據協調人的協議,我在這裏重新發布這個問題,並自己發佈接受的問題,因爲我認爲它包含一些有用的信息。

+4

如果你是在基準有興趣,你可能要檢查出[標準](http://hackage.haskell.org/package/criterion ) 圖書館。 – hugomg

+0

到達最後一行時,'foo'功能將不會執行。 Haskell函數只按需求進行評估,所以在賦值到'end'之前,你需要用'r'值做一些事情。 –

回答

15

回答最初由用戶ysdxon programmers給出:

你的確版本不會基準你的算法。由於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之前。

+2

通常的做法是讓自己免除爲他人工作的功勞,那就是製作答案社區維基。然後答案仍然可以upvoted /接受,但你不會得到信用:) –

+1

我不知道,謝謝。我已經設置了社區wiki標籤。現在,如果他們碰巧再次讀到這兩個upvoters可以刪除upvote。 – Giorgio

6

我會使用語言擴展-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) 
+1

這隻會評估結果到最外層的構造函數,在這裏,需要完整的評估。 –

+1

做爆炸模式確保完整的評估或將表達式減少到弱頭正常形式嗎(http://stackoverflow.com/questions/6872898/haskell-what-is-weak-head-normal-form)? – Giorgio

+0

你也可以在foo中使用BangPatterns。 –