2012-02-29 17 views
12

假設我創建了一個類型,如下所示:如何確定Haskell中的某個類型的大小?

data RequestAck = 
     RequestAck { ackOK :: Word32, ackMsgCode :: Word32 } 

我可以看到,它是2 * 4個字節大,使之成爲恆定的地方。

唯一的問題是,一旦我添加一個字段的類型,我不得不記得更新我的常量。

是否有一個函數可以提供給定類型的大小,如t -> Int

來接近我想要的功能是

gsize :: Data a => a -> Int

的Data.Generics.Schemes模塊內部,但我不希望有讓我的類型Data一個實例。

那裏有更通用的解決方案嗎?可以肯定,我正在尋找一種對靜態類型進行操作的函數,例如,我不想傳遞一個實例,而只是類型本身。

+2

提示:它不是2 * 4個字節大。字段被裝箱。 – 2012-02-29 02:55:02

+1

好點。在我的情況下,我拉出單詞並將它們轉換爲最終爲2 * 4字節長度的字節串。所以,現在回想起來,因爲這個原因,對於我來說這個類型的尺寸沒有多大意義。 – 2012-02-29 03:48:49

+2

「Haskell數據類型的內存佔用空間」:http:// stackoverflow。com/questions/3254758/memory-footprint-of-haskell-data-types,也是「如何找出GHC的數據類型的內存表示」http://stackoverflow.com/questions/6574444/how-to-find-out -ghcs-memory-representation-of-data-types – 2012-02-29 12:19:38

回答

11

這實際上取決於你如何將它轉換爲字節。

作爲Word32,沒有固定大小。你看到的Word32可能是一個未應用的閉包,佔用數百兆字節的空間。或者它可能是一個簡單的盒裝類型(它會大於4個字節)。或者它可能是某種內聯標記類型(在這種情況下,它取決於平臺)。或者它可能會被忽略(在這種情況下,它不存在)。

當你真的可以說這個尺寸是什麼時,你唯一的一次是當你轉換成二進制。如果你這樣做與FFI接口,你可以使用the sizeOf member of Foreign.Storable。當然,如果你想直接應用sizeOf,你需要爲你的類型編寫一個Storable實例。如果你通過Data.Binary序列化,那麼只需要序列化這個東西。您通常不需要事先知道實際大小(如果您需要大小標頭,只需將您計算大小的主體序列化爲臨時惰性字節串,然後取大小,然後寫入大小和溫度字節字符串)。

+2

根據你的建議來衡量實際的字節串大小,我改變了我的服務器/客戶端協議,在每個二進制消息前面加上一個包含後面ByteString大小的字(我事先測量)。感謝您的洞察力。 – 2012-03-01 03:06:41

1

bitSizeMaybefiniteBitSizeData.Bits提供了以位爲單位的大小。它們從同一模塊中取代bitSize

finiteBitSize :: b -> Int 

返回位在參數的類型的數量。參數的實際值 被忽略。

finiteBitSize = bitSize 
bitSizeMaybe = Just . finiteBitSize 

實例:

> import Data.Bits 
> finiteBitSize (42 :: Int) 
64