Da newtype
s beim Kompilieren effektiv entfernt werden, haben sie keine Thunks, nur Werte. Was passiert also, wenn ich nach seinem WHNF frage, indem ich % co_de verwende % ? Zum Beispiel in
wo rseq
ist definiert als
wird Sum
ausgewertet oder nicht? Ist es irgendwo spezifiziert / dokumentiert, damit ich mich darauf verlassen kann?
Update: Lassen Sie mich meine Zweifel genauer erklären. Intuitiv sagt man: " lengthyComputation
ist streng, so klar ist sein WHNF das WHNF dessen, was drin ist". Aber ich denke, das ist eine sehr ungenaue Abkürzung und die Argumentation ist nicht so klar. Lassen Sie mich ein Beispiel geben:
Für standardmäßige newtype
-Typen kann WHNF als ein Formular definiert werden, in dem wir wissen, welcher Konstruktor zum Erstellen des Werts verwendet wurde. Wenn wir zum Beispiel data
nicht hätten, könnten wir unser eigenes
und ähnlich für jeden seq
-Typ, nur durch Mustervergleich für einen seiner Konstruktoren.
Nun nehmen wir
%Vor% und erstellen Sie eine ähnliche Funktion data
:
klar, hier ist nichts zu WHNF gezwungen. (Immerhin wissen wir immer, welcher Konstruktor verwendet wurde.) Nach der Kompilierung ist seqIdentity
identisch mit seqIdentity
. Tatsächlich ist es nicht möglich, polymorph const id
so zu erstellen, dass die Auswertung eines Wertes, der in seqIdentity
! Wir könnten WHNF a von Identity
einfach als unmodifizierten Wert definieren und es wäre konsistent. Ich glaube also, die Frage ist, wie ist WHNF für newtype
s definiert? Oder gibt es keine strenge Definition, und das Verhalten "es ist die WHNF von dem, was drin ist" wird einfach als etwas Offensichtliches angenommen?
Im Abschnitt Umbenennungen von Datentypen im Bericht
>Im Gegensatz zu algebraischen Datentypen ist der newtype-Konstruktor N nicht verschoben, so dass N ⊥ dasselbe wie ⊥ ist.
Hier
%Vor%so ist die schwache Kopf-Normalform eines neuen Typs die WHNF des umschlossenen Typs und
%Vor% wertet lengthyComputation
aus (wenn der gesamte Ausdruck ausgewertet wird, eine bloße Bindung
natürlich nicht, aber das ist das gleiche ohne den Konstruktor newtype.
Die definierenden Gleichungen für seq
sind
und daher
%Vor%und in
%Vor% Die seq
wird benötigt, um herauszufinden, ob lengthyComputation :: Int
ist oder nicht. Dazu muss lengthyComputation :: Int
ausgewertet werden.
Re Aktualisierung:
newtype
s sind unlifted , dh der Konstruktor ist kein Wertkonstruktor semantisch (nur syntaktisch). Der Mustervergleich für einen newtype
-Konstruktor ist im Gegensatz zum Mustervergleich für einen data
-Konstruktor nicht streng. Gegeben
ein "Mustervergleich"
%Vor%entspricht vollständig
%Vor%Die Übereinstimmung ist immer erfolgreich und wertet nichts aus. Der Konstruktor erzwingt nur den Typ und "Mustererkennung" deaktiviert den Typ des Wertes.
seq
ist magisch, es kann nicht in Haskell implementiert werden. Sie können eine Funktion schreiben, die dasselbe tut wie seq
für einen data
type, wie Ihre seqMaybe
oben, in Haskell, aber nicht für eine (polymorphe) newtype
, weil "pattern matching" für den newtype Konstruktor ist nicht streng. Sie müssten die Konstruktoren des umschlossenen Typs anpassen, aber für eine polymorphe newtype
haben Sie sie nicht.
Tags und Links haskell concurrency lazy-evaluation newtype