2012-05-28 41 views
11

我聽說有一個GHC分支默認編譯爲嚴格代碼,而懶惰可以通過註釋啓用。 (IIRC,他說一家金融公司開發分支機構並將其用於生產代碼)。這是真的嗎?我找不到它。GHC的非延遲分支

該人還建議嚴格評估比懶惰評估(默認情況下)更實用的觀點越來越多地被接受。 我沒有在Haskell郵件列表中找到這個證實,但也許這是因爲那裏的人沒有那種實踐導向?

我在嚴格的Haskell上找到的所有內容都是明確的,如$!rnf。雖然我覺得懶惰評價非常優雅,但我想在Haskell中開發一個程序,我希望避免空間泄漏並希望具有可預測的性能。

聲明:我沒有嚴格要求,我只想看看嚴格的Haskell或類似的東西。

+0

我很好奇 - 你碰到什麼粗魯的驚喜? –

+1

(無可否認愚蠢的表達)粗魯的surpises我的意思是空間泄漏和運行時間的不可預測性。其實我沒有碰到他們,但在我看來,這些問題是真實的,對嗎? (我目前正在評估使用哪種語言。) – chs

+2

我認爲這可能被稱爲'Mu'?倫納特·奧古斯特森可能在某處提到過它。 – jtobin

回答

12

您正在尋找Disciple

所以在Haskell中有兩種懶惰區分。有懶惰的I/O,這是一種憎惡,並通過迭代庫(Shameless插件:包括我的pipes庫)解決。再有就是懶惰純計算,這仍然是開放的辯論,但我會試着總結一下懶惰的關鍵優勢,因爲你已經熟悉的缺點:

懶惰是更有效的

一簡單的例子是:

any = foldr (||) False 

any發現如果在列表中的任何值是True。這隻對第一個True的元素進行評估,因此列表是否很長並不重要。

懶惰只計算儘可能多的,這意味着如果您將兩個懶惰計算鏈接在一起,它實際上可以提高計算結果的時間複雜度。 This Stack Overflow comment給出了另一個很好的例子。

這實際上是迭代器庫非常有效的資源效率的原因。他們只做儘可能多的工作,因爲他們必須產生結果,這導致非常有效的內存和磁盤使用以及非常易於使用的語義。

懶惰是本質上更可組合

這很好誰已經在這兩個嚴格函數式語言編程的人所熟知,但其實我無意中證明了這一點,而在pipes圖書館,在那裏工作的有限證據懶惰版本是允許使用Category實例的唯一版本。管道實際上工作在任何monad中,包括純粹的Identity monad,所以我的證明也轉化爲純代碼。

這就是爲什麼我相信懶惰總體上真的是編程的未來的真正原因,但我仍然認爲這是一個開放的問題,Haskell是否實施了「正確」的懶惰。

+0

很好地處理這個話題的視頻講座可以免費獲得[here](http://videoag.fsmpi.rwth-aachen.de/?view=player&videoid=2034#content)。 (注:視頻是英文的,我與亞琛的視頻或大學沒有任何關係) – dflemstr

+2

我認爲懶惰的主要優點是它提供了靈活性和關注點分離。在一種想要被認爲是聲明性的語言中,它也是必要的。在理想的haskell中,它的評估模型只是一個實現細節。 – jberryman

+0

@jberryman對,我想說的是,只要說只有懶惰才能形成一個類別,這種「靈活性」和「關注點分離」的直覺才能變得嚴謹。 –

1

如果我的理解正確,嚴格的Haskell就不會有我們所知道的monadic I/O。Haskell的想法是所有的Haskell代碼都是純粹的(包括IO操作,就像狀態monad一樣),「main」給運行時提供IO()類型的值,然後重複對測序操作符>> = 。

對於Tekmo的文章的對口,你可以看看羅伯特哈珀的博客, * http://existentialtype.wordpress.com/2011/04/24/the-real-point-of-laziness/ 和相關。它是雙向的。

根據我的經驗,懶惰起初很困難,但後來你習慣了,它很好。

懶惰的經典宣傳片段是休斯的論文「爲什麼函數式編程很重要」,您應該能夠輕鬆找到它。

+5

Monadic IO不依賴於懶惰。 – is7s

+0

你不需要強制'>> ='; 'getLine >> = putStrLn'是一個完全獨立的表達式,它產生一個完成它所說的動作,並且可以在實際執行IO動作之前完全評估它。 – Ashe

3

關於爲什麼你不應該回避Haskell的懶惰,一些好的事情已經說了,但我覺得原來的問題仍然沒有得到答案。

函數在Haskell中的應用並不嚴格;也就是說,只有在需要時纔會評估函數參數。

Haskell Report 2010 > Predefined Types and Classes # Strict Evaluation

這是一個有點誤導,但是。實現可以在需要之前評估函數參數,但僅限於有限的範圍。你必須保留非嚴格的語義:所以如果一個參數的表達式導致一個無限循環,並且該參數沒有被使用,那麼帶有該參數的函數調用不能無限循環。

所以你允許以一種不完全「懶惰」的方式實現Haskell,但它也不能是「嚴格」。這看起來似乎是第一反應,但事實並非如此。您可能想要查看的幾個相關主題:

4

這聽起來像你聽說過Robert Ennals的PhD thesis on speculative evaluation與GHC。他創建了一個名爲「spec_eval」的GHC分支,在那裏進行投機評估。由於Haskell不是嚴格的而不是明顯的惰性,spec_eval 嚴格的,直到它實際上有所作爲。儘管在所有情況下速度都比較快,但它需要對GHC進行大的改動,而且從未合併過。

此問題已在本網站上排序been answered before