Entpackt GHC Sum-Typen, wenn sie an Funktionen übergeben werden? Zum Beispiel, sagen sie, dass wir den folgenden Typen haben:GHC-Aufrufkonvention für Sum-Typ Funktionsargumente
data Foo
= Foo1 {-# UNPACK #-} !Int {-# UNPACK #-} !Word
| Foo2 {-# UNPACK #-} !Int
| Foo3 {-# UNPACK #-} !Word
Dann definiere ich eine Funktion, die in seinem Foo
Argumente streng:
consumeFoo :: Foo -> Int
consumeFoo x = case x of ...
Zur Laufzeit, wenn ich consumeFoo
nennen, was ich kann erwarten zu passieren? Das GHC calling convention soll Argumente in Registern übergeben (oder auf dem Stack, wenn es zu viele gibt). Ich kann auf zwei Arten sehen, dass die Argumentübergabe gehen könnte:
- Ein Zeiger auf ein
Foo
auf dem Heap übergeben wird als ein Argument in. - Eine dreiargumentale Darstellung von
Foo
wird verwendet, wobei ein Argument den verwendeten Datenkonstruktor und die anderen beiden die möglichen WerteInt
undWord
im Datenkonstruktor darstellen.
Ich würde die zweite Darstellung bevorzugen, aber ich weiß nicht, ob es tatsächlich ist, was passiert. Ich bin mir bewusst, UnpackedSumTypes Landung in GHC 8.2, aber es ist unklar, ob es tut, was ich will. Hätte ich stattdessen die Funktion geschrieben als:
Dann würde ich erwarten, dass Auswertung (2) wäre was passiert. Und die Unpacking section der entpackten Summen Seite zeigt an, dass ich dies tun könnte auch:
data Wrap = Wrap {-# UNPACK #-} !Foo
consumeFooAlt2 :: Wrap -> Int
Und das sollte auch die Darstellung habe ich möchte, glaube ich.
Also meine Frage ist, ohne Verwendung eines Wrappertyps oder einer unverpackten Summe, wie kann ich garantieren, dass eine Summe in Register (oder auf den Stapel) entpackt wird, wenn ich es als Argument an eine Funktion übergebe? Wenn es möglich ist, ist es etwas, das GHC 8.0 bereits kann, oder ist es etwas, das nur in GHC 8.2 verfügbar sein wird?