2012-02-29 23 views
12

Załóżmy I stworzył typ następująco:Jak określić rozmiar typu w Haskell?

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

widzę, że jest to 2 * 4 bajty duże i sprawiają, że stała gdzieś.

Jedynym problemem jest to, że po dodaniu pola do typu, musiałbym pamiętać o aktualizacji mojej stałej.

Czy istnieje funkcja, która zapewni mi rozmiar danego typu, np. t -> Int?

Funkcja, która zbliża się do tego, co chcę jest

gsize :: Data a => a -> Int

wewnątrz modułu Data.Generics.Schemes, ale nie chcę mieć, aby mój typ instancję Data.

Czy istnieje bardziej ogólne rozwiązanie?

Z pewnością szukam funkcji działającej na statycznym typie, np. Nie chcę przekazywać instancji, ale samego typu.

+2

wskazówka: Nie 2 * 4 bajty duże. Pola są w pudełku. –

+1

Dobra uwaga. W moim przypadku wyciągam słowa i zamieniam je na test bytowy, który kończy się 2 * 4 bajtami. Tak więc z perspektywy czasu określenie rozmiaru tego typu nie miałoby dla mnie większego sensu z tego powodu. –

+2

"Ślad pamięci typów danych Haskella": http: // stackoverflow.com/questions/3254758/memory-footprint-of-haskell-data-types, także "Jak znaleźć dane GHC o typach danych" http://stackoverflow.com/questions/6574444/how-to-find-out -ghcs-memory-reprezentacje-danych-typów –

Odpowiedz

11

To naprawdę zależy od tego, jak zamieniasz to w bajty.

Jako Word32 nie ma ustalonego rozmiaru. To, co widzisz jako Word32, może być niezastosowanym zamknięciem zajmującym setki megabajtów przestrzeni. Lub może to być prosty typ pudełkowy (który będzie większy niż 4 bajty). Lub może to być rodzaj wbudowanego tagowanego typu (w tym przypadku zależy to od platformy). Lub może być elected (w tym przypadku nie istnieje).

Jedynym momentem, w którym można naprawdę powiedzieć, jaki jest rozmiar, jest konwertowanie na format binarny. Jeśli robisz to, aby łączyć się z FFI, możesz użyć the sizeOf member of Foreign.Storable. Oczywiście, musisz napisać Stałe wystąpienie dla swojego typu, jeśli chcesz zastosować do niego tylko sizeOf. Jeśli serializujesz za pomocą Data.Binary ... cóż, po prostu serializuj to, naprawdę. Zwykle nie musisz znać faktycznego rozmiaru wcześniej (i jeśli robisz dla nagłówka rozmiaru, tylko serializować ciało, które liczą rozmiar do tymczasowego leniwego bytestringa, następnie weź rozmiar, a następnie napisz rozmiar i temp bytestring).

+2

Zgodnie z twoją sugestią pomiaru rzeczywistego rozmiaru ByteString, zmieniłem mój protokół serwer/klient, aby prefiksować każdą wiadomość binarną słowem, które zawiera rozmiar ByteString, który następuje (który wcześniej mierzę). Dzięki za ten wgląd. –

1

bitSizeMaybe i finiteBitSize z Data.Bits podać rozmiar w bitach. Zastępują one bitSize z tego samego modułu.

finiteBitSize :: b -> Int 

zwrócić liczbę bitów w rodzaju sporu. Rzeczywista wartość argumentu jest ignorowana.

finiteBitSize = bitSize 
bitSizeMaybe = Just . finiteBitSize 

Przykład użycia:

> import Data.Bits 
> finiteBitSize (42 :: Int) 
64 
Powiązane problemy