2012-12-02 5 views
8

Da newtype s während der Kompilierung effektiv entfernt werden, haben sie keine Thunks, nur Werte. Was passiert also, wenn ich nach WHNF mit rseq frage? Zum Beispiel inWas ist der WHNF eines neuen Typs und wie arbeitet RSEQ an einem neuen Typ?

Sum (lengthyComputation :: Int) `using` rseq 

wo Sum ist definiert als

newtype Sum a = Sum { getSum :: a } 

wird lengthyComputation ausgewertet oder nicht erhalten? Ist es irgendwo angegeben/dokumentiert, damit ich mich darauf verlassen kann?


Update: Lassen Sie mich meine Zweifel näher erläutern. Intuitiv sagt man: "newtype ist streng so klar, dass sein WHNF das WHNF dessen ist, was innen eingewickelt wird". 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 Standard data Typen kann WHNF als eine Form definiert werden, wo wir wissen, welcher Konstruktor für die Konstruktion des Werts verwendet wurde. Wenn zum Beispiel haben wir nicht seq haben, konnten wir unsere eigenen

seqMaybe :: Maybe a -> b -> b 
seqMaybe Nothing = id 
seqMaybe _  = id 

erstellen und in ähnlicher Weise für jede data Art, nur durch Muster auf einer seiner Konstrukteure entsprechen.

Jetzt ist

newtype Identity a = Identity { runIdentity :: a } 

und erstellen eine ähnliche seqIdentity Funktion übernehmen lassen:

seqIdentity :: Identity a -> b -> b 
seqIdentity (Identity _) = id 

klar, nichts gezwungen hier WHNF. (Immerhin wissen wir immer, welcher Konstruktor verwendet wurde.) Nach der Kompilierung ist seqIdentity identisch mit . In der Tat ist es nicht möglich, polymorph seqIdentity so zu erstellen, dass es die Auswertung eines Werts innerhalb Identity eingezwängt würde! Wir könnten WHNF a von newtype einfach als den Wert unmodifiziert definieren und es wäre konsistent. Also ich glaube, 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?

Antwort

8

pro Abschnitt über Datatype renamings in dem Bericht,

Im Gegensatz zu algebraischen Datentypen wird der newtype Konstruktor N nicht angehoben, so dass N ⊥ ist die gleiche wie ⊥.

Hier

Sum ⊥ = ⊥ 

so die schwache Kopfnormalform einer newtype die WHNF des umschlossenen Typs ist, und

Sum (lengthyComputation :: Int) `using` rseq 

wertet lengthyComputation (wenn der gesamte Ausdruck ausgewertet wird, ein Bindung

let x = Sum (lengthyComputation :: Int) `using` rseq 

natürlich nicht, aber das ist das Gleiche ohne den newtype Konstruktor).

Die defining equations für seq sind

seq ⊥ b = ⊥ 
seq a b = b, if a ≠ ⊥ 

und damit

seq (Sum ⊥) b = ⊥ 

und in

seq (lengthyComputaton :: Int) b 

der seq erforderlich ist, um herauszufinden, (für die Anthropomorphismus sorry), ob lengthyComputation :: Int ist ⊥ oder n ot. Dazu muss lengthyComputation :: Int ausgewertet werden.


Re Update:

newtype s sind nicht angehobenen, bedeutet das, dass der Konstruktor kein Wert Konstruktor ist semantisch (nur syntaktisch). Pattern-Matching auf einem newtype Konstruktor ist im Gegensatz zum Mustervergleich auf einen data Konstruktor nicht streng. Angesichts

newtype Foo a = Foo { unFoo :: a } -- record syntax for convenience below 

ein "Mustererkennung"

function :: Foo a -> Bar 
function (Foo x) = whatever x 

ist völlig gleichwertig

function y = let x = unFoo y in whatever x 

Das Spiel immer erfolgreich ist, und wertet nichts. The constructor only coerces the type und "Mustererkennung" deaktiviert den Typ des Werts.

seq ist magisch, es kann nicht in Haskell implementiert werden. Sie können eine Funktion schreiben, die das gleiche wie seq für einen data Typ, wie Ihre seqMaybe oben, in Haskell, aber nicht für eine (polymorphe) tut, weil "Mustererkennung" auf den newtype Konstruktor nicht streng ist. Sie müssten die Konstruktoren des umschlossenen Typs anpassen, aber für einen polymorphen newtype haben Sie keine.

+0

Vielen Dank für Ihre Antwort. Aber ich denke, dass der Schritt "newtype" streng ist, so dass sein WHNF das WHNF dessen ist, was drin ist "ist nicht präzise. Ich änderte die Frage und versuchte, meine Zweifel ausführlich auszudrücken. –

+2

Es ist nicht so, dass "newtype's streng sind, es ist, dass sie _unlifted_ sind, die die WHNF propagieren lassen. –

+0

Erweiterte Antwort, klärt das mehr? –