2010-06-28 84 views
23

無盒類型,如Int#和嚴格函數,如f (!x) = ...,有些不同,但我看到概念上的相似性 - 它們以某種方式不允許thunk/laziness。如果Haskell是像Ocaml這樣嚴格的語言,那麼每個函數都將是嚴格的,每種類型都會被拆箱。拆箱類型和嚴格執行之間的關係是什麼?拆箱類型和嚴格性之間的關係是什麼?

+1

我對拆箱類型沒有太多經驗,所以即使是基本的評論也是受歡迎的。 – sdcvvc 2010-06-28 10:22:59

+3

由於多態性,並非所有類型都將被拆箱。 OCaml和Haskell中的多態函數使用值的統一表示法作爲閉包。 Haskell允許專門化,生成使用非盒裝參數的自定義函數(OCaml可能也會這樣做)。 – 2010-06-28 16:36:14

回答

32

無盒裝VS盒裝數據

爲了支持parametric polymorphismlaziness,默認情況下Haskell的數據類型被統一表示爲一個指向closurethe heap,具有這樣的結構:

alt text

這些是「盒裝」值。一個拆箱對象由值本身直接表示,沒有任何間接或閉包。 Int已裝箱,但Int#已取消裝箱。

懶惰值需要一個盒裝表示。嚴格的值不會:它們可以表示爲堆中完全評估的閉包,或者表示爲原始的拆箱結構。請注意,pointer tagging是我們可以在盒裝對象上使用的優化,用於將指針中的構造函數編碼爲閉包。

的關係,以嚴格

通常,在由功能語言編譯器的特設的方式生成裝箱值。但在Haskell中,unboxed values是特殊的。他們:

  1. 他們有不同的種類,#;
  2. 只能在特殊的地方使用;和
  3. 它們未被提升,所以不被表示爲指向堆值的指針。

因爲它們未被提升,所以它們必然是嚴格的。懶惰的表示是不可能的。

因此,特別的拆箱類型,例如Int#,Double#,在機器上確實表示爲double或int(以C表示法)。

嚴謹分析

另外,GHC不正規的Haskell類型strictness analysis。如果一個值的使用被認爲是嚴格的 - 也就是說它永遠不會被定義爲'未定義的 - 優化器可能會取代常規類型的所有用途(例如Int)與一個非盒裝的(Int#),因爲它知道使用Int是總是嚴格的,因此用更高效(並且總是嚴格)的類型Int#替換是安全的。

我們當然可以有嚴格的類型,而拆箱類型,例如,一個元素嚴格多態性名單:

data List a = Empty | Cons !a (List a) 

是其元素嚴格,但並不代表他們作爲拆箱值。

這也指出了您對嚴格語言做出的錯誤like OCaml。他們仍然需要支持多態,所以他們提供一個統一的表示,或者他們專門爲每種類型提供數據類型和函數。 GHC默認使用統一表示法,就像OCaml一樣,儘管GHC現在也可以使用specialize types and functions(如C++模板)。

+0

那麼有沒有使用嚴格的盒裝類型,就像你的'List'例子?它是否與懶惰的對象具有相同的表示形式? – haskelline 2012-07-03 08:15:03

+0

它具有相同的表示形式,但語義不同。這樣的結構通常是有用的。 – 2012-07-03 12:29:22

+1

但我認爲,例如'data Pair = P Int Int'將包含比'data Pair = P!Int!Int'更多的間接字符。在前者中,每個參數是指向一個指針(一個thunk)的指針,而在後者中它是一個指向值的指針? – haskelline 2012-07-03 13:25:57

17

拆箱類型必然是嚴格的,但並非所有嚴格的值都必須拆箱。

data Foo a = Foo !a !a 

有兩個嚴格的領域

data Bar a = Bar {-# UNPACK #-} !Int !a 

有兩個嚴格的領域,但第一個是拆箱。

最終,unboxed類型(必然)嚴格的原因是沒有地方存儲thunk,因爲它們只是扁平的,在那一點上是啞數據。任何類型的

7

參數可以由「嚴格」,但具有相應boxed類型的唯一的裝箱類型是Char#Int#Word#Double#Float#

如果您知道像C這樣的低級語言,則更容易解釋。無盒類型類似於int,double等,盒裝類型與int*,double*等相同。當您有int時,您已經知道整個值,因爲它是以位模式表示的,因此它不是懶。它也必須嚴格,因爲所有int的值都是有效的,而不是⊥。

但是,給定int*後,您可能會選擇取消引用指針以獲取實際值(因此爲惰性),並且可能包含無效指針(它包含⊥,即非嚴格指針)。

相關問題