Jaki jest związek między typami bez pudełek a ścisłością?
Typy Nieboskłonowe, jak Int#
, i funkcje ścisłe, jak f (!x) = ...
, to coś innego, ale widzę podobieństwa pojęciowe - w jakiś sposób uniemożliwiają thunks/lenistwo. Gdyby Haskell był językiem ścisłym, takim jak Ocaml, każda funkcja byłaby ścisła, a każdy typ nie był zdefiniowany. Jaki jest związek między typami bez pudełek a egzekwowaniem surowości?
3 answers
Unboxed vs Boxed Data
Aby wspierać polimorfizm parametryczny i lenistwo , domyślnie typy danych Haskell są reprezentowane jednolicie jako wskaźnik do zamknięcia na stercie, o strukturze takiej jak:
Są to wartości "pudełkowe". Obiekt unboxed jest reprezentowany przez samą wartość bezpośrednio, bez żadnego podziału lub zamknięcia. Int
jest w pudełku, ale {[2] } jest w pudełku.
Leniwy wartości wymagają reprezentacji pudełkowej. Wartości ścisłe nie: mogą być reprezentowane albo jako w pełni ocenione zamknięcia na stercie, albo jako prymitywne struktury nieokreślone. Zauważ, że znacznik wskaźnika jest optymalizacją, której możemy użyć na obiektach pudełkowych, aby zakodować konstruktor w wskaźniku do zamknięcia.
Związek ze ścisłością
Zwykle wartości nieboxowane są generowane ad hoc przez kompilatory języka funkcjonalnego. W Haskell, jednak unboxed wartości {[16] } są specjalne. Oni:
- majÄ… inny rodzaj,
#
; - może być używany tylko w specjalnych miejscach; i
- nie są podnoszone, więc nie są reprezentowane jako wskaźnik do wartości sterty.
ponieważ są one niezniszczalne, są koniecznie surowe. przedstawienie lenistwa nie jest możliwe.
Tak szczególne typy nieboskłonowe, jak Int#
, Double#
, naprawdę są reprezentowane jako podwójne lub int na maszyna (w notacji C).
Analiza Ścisłości
Oprócz tego GHC przeprowadza analizę ścisłości typowych typów Haskell. Jeśli użycie wartości okaże się ścisłe – tzn. nigdy nie może być 'undefined' – optymalizator może zastąpić wszystkie zastosowania zwykłego typu (np.Int
) niezakłóconym (Int#
), ponieważ wie, że użycie {[1] } jest zawsze ścisłe, a zatem zastąpienie go bardziej wydajnym (i zawsze ścisłym) typem Int#
jest bezpieczne.
We można oczywiście mieć typy strict bez typów unboxed, na przykład lista polimorficzna element-strict:
data List a = Empty | Cons !a (List a)
Jest ścisły w swoich elementach, ale nie przedstawia ich jako wartości nieobsługiwanych.
To również wskazuje na błąd, który popełniłeś w odniesieniu do ścisłych języków, , takich jak OCaml . Nadal muszą wspierać polimorfizm, więc albo zapewniają jednolitą reprezentację, albo specjalizują typy danych i funkcje do każdego typu. GHC domyślnie używa jednolitej reprezentacji, jako czy OCaml, choć GHC może również specjalizować typy i funkcje teraz (jak szablony C++).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-08 14:27:42
Typy nieobsługiwane są bezwzględnie, ale nie wszystkie wartości bezwzględne są bezwzględnie nieobsługiwane.
data Foo a = Foo !a !a
Posiada dwa ścisłe pola
data Bar a = Bar {-# UNPACK #-} !Int !a
Ma dwa ścisłe pola, ale pierwsze z nich nie jest pudełkowe.
Ostatecznie, powodem, dla którego typy bez pudełek są (koniecznie) ścisłe, jest to, że nie ma miejsca na przechowywanie thunk, ponieważ są to tylko płaskie, głupie dane w tym momencie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-03 06:43:32
Argumenty dowolnego typu mogą być "ścisłe", ale jedynymi typami nieobsługiwanymi, które mają odpowiednie typy pudełkowe, są Char#
, Int#
, Word#
, Double#
i Float#
.
Jeśli znasz języki niskiego poziomu, takie jak C, łatwiej to wyjaśnić. Unboxed typy są jak int
, double
, itd., a typy pudełkowe są jak int*
, double*
, itd. Kiedy masz int
, znasz już całą wartość, ponieważ jest ona reprezentowana we wzorze bitowym, dlatego nie jest ona leniwa. Musi być również ścisły, ponieważ wszystkie wartości int
są ważne i nie są ważne.
Jednak, biorÄ…c pod uwagÄ™ int*
można wybrać, aby później dereferować wskaźnik, aby uzyskać rzeczywistą wartość( a więc leniwy), i możliwe jest, aby mieć nieprawidłowe wskaźniki (zawiera ⊥, tzn. non-strict).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-28 16:40:43