2013-10-21 92 views
0
功能的

讓假設我們有一個函數性能改變功能

type Func = Bool -> SophisticatedData 
fun1 :: Func 

,我們想改變這個功能的一些輸入:右

change :: SophisticatedData -> Func -> Func 
change data func = \input -> if input == False then data else func input 

我是那之後的幾個電話changeendFunc = change data1 $ change data2 $ startFunc)生成的函數會每次調用所有中間函數?我是否確定GC無法刪除未使用的數據?什麼是Haskell的方式來應對這項任務?

謝謝。

+1

隨着GHC,你甚至不會計算數據,直到它的需要(懶洋洋),或者如果您已被迫評價GC應該能夠清理之後沒有更多的參考資料。 – bheklilr

+2

附註:'data'是關鍵字,不能用作變量名稱。 –

回答

3

那麼讓我們來通過清理變化多一點清晰

change sd f input = if input then func input else sd 

因此,開始的時候,我們通過存儲爲他們每個人一個thunk撰寫這些

change d1 $ change d2 $ change d3 

GHC開始。請記住$是一個函數,因此整個change d*事情一開始就會變成一個thunk。 Thunk相對便宜,如果你一次不創建10k左右的話,你就會很好:)所以不用擔心。

現在的問題是,當你開始評估時會發生什麼,答案是,它仍然不會評估複雜的數據,所以它仍然非常有效,並且只需要強制input來確定它正在使用哪個分支。因此,在選擇運行並返回一個給你之前,你應該永遠不要完全評估SophisticatedData,那麼如果你使用它,它將被評估爲需要。

此外,在每一步,GHC都可以垃圾收集不需要的thunk,因爲它們不能再被引用。

總之,你應該沒問題。信任懶惰

+0

所以,如果我有'$'s的O(n),每次調用這個函數都是O(n)? – ElectricHedgehog

+0

@ElectricHedgehog空間還是速度? – jozefg

+0

速度。我認爲所有呼叫的空間總數都是O(n)。 – ElectricHedgehog

1

你是對的:如果foo是O(n)調用到change的鏈,那麼在每次調用foo時都會有O(n)開銷。處理這個問題的方法是memoize的foo

memoize :: Func -> Func 
memoize f = \x -> if x then fTrue else fFalse where 
    fTrue = f True 
    fFalse = f False 
+0

你說得對,但你應該在'fTrue = f $!中添加'$!'運算符! TRUE'。在另一種情況下,評估將是懶惰的,而且每次都會計算'memoize'函數。 – ElectricHedgehog

+0

@ElectricHedgehog您聲稱'fTrue'會是懶惰的,但您聲稱memoized函數每次都會產生O(n)代價是錯誤的。自己測試! –