2012-01-20 45 views
11

多次調用我這樣說的:ViewPatterns和哈斯克爾

http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns

我喜歡這個主意,想用擴展。然而,我想確保一件事:視圖函數是否僅針對單個匹配進行一次評估。

所以我們可以說,我們有:

現在,讓我們說,我調用f a。對於給定的參數aview被調用兩次或只調用一次?

編輯

我試圖找出是否是這種情況,並寫道:使用GHC

{-# LANGUAGE ViewPatterns #-} 

import System.IO.Unsafe 

blah (ble -> Nothing) = 123 
blah (ble -> Just x) = x 

ble x = unsafePerformIO $ do 
    putStrLn $ "Inside ble: " ++ show x 
    return x 

main :: IO() 
main = do 
    putStrLn $ "Main: " ++ show (blah $ Just 234) 

輸出:

Inside ble: Just 234 
Inside ble: Just 234 
Main: 234 

使用GHC輸出(帶優化)

Inside ble: Just 234 
Main: 234 

輸出使用GHCI:

Main: Inside ble: Just 234 
Inside ble: Just 234 
234 
+0

GHC有避免重新計算相同視圖表達式的特殊方法。 – augustss

回答

13

只需一次:

效率:當相同的功能時在函數定義或的情況下表達的 多個分支施加(例如, 在size以上),GHC嘗試將這些 應用程序收集到單個嵌套的大小寫表達式中,以便功能只能應用一次。 GHC中的模式編譯遵循在The Implementation of Functional Programming Languages的第4章中描述的 矩陣算法。當矩陣第一列的頂部行都是 「相同」表達式的查看模式時,這些模式將轉換爲單個嵌套的 大小寫。這包括,例如,相鄰的視圖模式,在元組排隊 ,如在

 
f ((view -> A, p1), p2) = e1 
f ((view -> B, p3), p4) = e2 

當兩個視圖圖案表達式的當前概念「的 相同」受到很大限制:它甚至沒有滿句法平等。然而,它確實包括變量,文字,應用程序和元組; 例如,view ("hi", "there")的兩個實例將被收集到 。但是,當前的實現不會與 alpha-equivalence進行比較,因此(x, view x -> y)的兩個實例將不會合並。

- The GHC manual

至於你的片斷,問題是,你不優化的編譯;與ghc -Oghc -O2,線只打印一次。這是永遠的第一件事就是檢查你使用的時候有性能相關的問題GHC :)

(順便說一句,Debug.Trace可以檢查這些事情,而無需編寫手冊unsafePerformIO黑客。)

+0

由於performUnsafeIO,GHC是否有可能插入額外的備用評估?別擔心,我只是用它來測試功能。 – julkiewicz

+0

我已經添加了一個具體的代碼示例。 – julkiewicz

+0

@julkiewicz:我已經更新了我的答案:) – ehird