O ile nie przechowujesz dużych obliczeń w polach Int i Float, znaczny narzut może narastać dzięki wielu trywialnym obliczeniom budującym się w tony. Na przykład, jeśli wielokrotnie dodajesz 1 do leniwego pola Float w typie danych, zużywa ono coraz więcej pamięci, aż w rzeczywistości wymusisz na polu, obliczając to.
Często chcesz przechowywać kosztowne obliczenia w polu. Ale jeśli wiesz, że nie zrobisz czegoś takiego z wyprzedzeniem, możesz oznaczyć to pole jako ścisłe i unikać ręcznego dodawania wszędzie, aby uzyskać pożądaną efektywność.
Jako dodatkowy bonus, kiedy podano flagę -funbox-strict-fields
GHC rozpakuje surowe pola typów danych bezpośrednio do samego typu danych, co jest możliwe, ponieważ wie, że zawsze będą oceniane, a zatem nie thunk musi być przydzielone; w tym przypadku wartość pręta zawierałaby słowa maszynowe zawierające Int i Float bezpośrednio wewnątrz wartości pręta w pamięci, zamiast zawierać dwa wskaźniki do brył, które zawierają dane.
Lenistwo jest bardzo użyteczną rzeczą, ale w niektórych przypadkach po prostu przeszkadza i utrudnia obliczenia, szczególnie w przypadku małych pól, na które zawsze patrzy się (a zatem wymuszane) lub które są często modyfikowane, ale nigdy nie bardzo kosztowne obliczenia. Surowe pola pomagają przezwyciężyć te problemy bez konieczności modyfikacji wszystkich zastosowań typu danych.
To, czy jest bardziej powszechne niż leniwe pola, zależy od rodzaju kodu, który czytasz; prawdopodobnie nie zobaczysz, że jakiekolwiek funkcjonalne struktury drzew używają na przykład ścisłych pól, na przykład, ponieważ bardzo korzystają z lenistwa.
Powiedzmy masz AST z konstruktora dla operacji infiksowych:
data Exp = Infix Op Exp Exp
| ...
data Op = Add | Subtract | Multiply | Divide
nie chcesz, aby pola Exp
surowe, jak stosując politykę jak oznaczałoby to, że cała AST jest oceniany za każdym razem, gdy patrzysz na węzeł najwyższego poziomu, co oczywiście nie jest tym, co chcesz czerpać z lenistwa. Jednak pole Op
nigdy nie będzie zawierało kosztownych obliczeń, które chcesz odłożyć do późniejszego terminu, a obciążenie związane z operacją thunk per infix może stać się drogie, jeśli masz naprawdę głęboko zagnieżdżone parsowanie. Tak więc dla konstruktora infiksów, musisz ustawić pole Op
jako surowe, ale pozostawić dwa pola leniwy Exp
.
Tylko typy jednego konstruktora mogą być rozpakowane.
Czy AST nie powinno być tak surowe? – Lanbo
Rozszerzyłem moją odpowiedź o kilka opracowań, używając AST jako przykładu. – ehird