Entwickeln eines Tests der Haskellschen Wert- / Referenzsemantik


8

In imperativen Sprachen ist es trivial, einen Programmiertest für die Verwendung von "Wertesemantik" oder "Referenzsemantik" durch die Sprache zu entwickeln. Man könnte folgendes tun und den Wert von a(wo Vertex {one, two, three :: Integer}) überprüfen :

a := Vertex 3 4 5
b := a
one b   :=  6
two b   :=  8
three b := 10

Da Variablen in funktionalen Sprachen unveränderlich sind, funktioniert dieser Test in solchen Sprachen nicht.

Ich weiß sehr wenig über Haskell (und die funktionale Programmierung im Allgemeinen), aber ich verstehe, dass sie Wertesemantik verwendet. Ist es möglich, ein Programmierexperiment zu entwickeln, das in Haskell zwischen einem "Ref-Datensatz" und einem "Val-Datensatz" unterscheidet?


1
Meinten Sie im zweiten Satz "Überprüfen Sie den Wert von a"?


Haskell ist referenziell transparent , [1] was bedeutet, dass 'Wertesemantik' und 'Referenzsemantik' in Haskell äquivalent sind. [1] Programmiersprachenfreaks werden eine lange Debatte über diese Aussage führen, aber es ist ziemlich traditionell, sie in dem Sinne zu verwenden, wie ich es gerade getan habe.
Jonathan Cast

Antworten:


9

Es gibt keinen solchen Test, da die Unterscheidung ohne Veränderbarkeit nicht aussagekräftig ist (wie Sie gezeigt haben).


3
Es ist erwähnenswert, dass einige Teile von Haskell ( IORef, MVarusw.) veränderlich sind und sich als Referenzen verhalten ( hpaste.org/81192 )
Daniel Gratzer

9

Haskell hat keine Referenzen (eine Referenz ist ein veränderbares Objekt, und Haskell hat keine (direkt zugänglichen) veränderlichen Objekte). Daher verwenden Funktionsaufrufe standardmäßig eine Wertesemantik. Dies ist in der Tat eine wichtige Eigenschaft reiner funktionaler Sprachen: Eine Funktion kann ihr Argument nicht ändern.

Die Wertesemantik bedeutet nicht , dass das Kopieren unter der Haube erfolgt. Sie müssen nur den Teil eines Werts kopieren, den die Funktion ändert. In einer reinen Sprache bedeutet dies, dass Sie niemals etwas kopieren müssen.

Dies ist jedoch nicht die ganze Geschichte. In gewissem Sinne hat Haskell Referenzsemantik.

Während es sinnlos ist zu testen, ob eine Funktion ihr Argument ändert (was sie niemals tut), können Sie testen, ob eine Funktion ihr Argument verwendet (einen Teil davon). Geben Sie ein Argument an, das nicht endet. Wenn der Funktionsaufruf beendet wird, wissen Sie, dass die Funktion ihr Argument nicht verwendet hat.

let bottom = bottom
let ignore x = 1
ignore bottom

Wenn Sie auswerten bottom, wird es nicht beendet: bottomerweitert sich zu sich selbst, ad nauseam. Der Begriff bottomkann keinen Wert haben. Aber wenn Sie auswerten ignore bottom, ist der Wert 1. Dies zeigt, dass für den Aufruf der Funktion ignorenicht der Wert ihres Arguments berechnet werden muss. In diesem Sinne hat Haskell eine Referenzsemantik: Was eine Funktion empfängt, ist kein Wert, sondern etwas, mit dem dieser Wert gefunden werden kann. Der Fachbegriff lautet Call by Name (im Gegensatz zu Call by Value ).

(Genauer gesagt verwenden Haskell-Implementierungen call by need . Bei call by value wird das Argument einer Funktion genau einmal ausgewertet, unmittelbar bevor die Funktion aufgerufen wird. Bei call by name wird das Argument jedes Mal ausgewertet, wenn es verwendet wird von nie bis so oft, wie die Funktion es wünscht. Bei Bedarf wird das Argument höchstens einmal ausgewertet: Es wird bei der ersten Verwendung ausgewertet oder niemals, wenn es nicht verwendet wird.)


2
Natürlich sind Call-by-Need und Call-by-Name in einer reinen Sprache nicht zu unterscheiden. Call-by-Need wird dann einfach zu einer Optimierungsstrategie.
Jörg W Mittag

2
@ JörgWMittag Guter Punkt, das habe ich vergessen zu erwähnen. (Übrigens ist Call-by-Need nicht immer effizienter als Call-by-Name, wenn Sie im endlichen Speicher arbeiten.)
Gilles 'SO - hör auf, böse zu sein'

1
Ja, aber wer hat nur endliches Gedächtnis? Wir benutzen alle Turingmaschinen, richtig? Im Ernst: Ich nehme an, das liegt daran, dass Sie einen gewissen Aufwand für die Buchhaltung haben, ob Sie den Wert "brauchen" oder nicht, oder? ZB Thunks oder so?
Jörg W Mittag

3
@ JörgWMittag Aber selbst in einer Turing-Maschine ist der Speicher eine Einschränkung, da das Erreichen des nützlichen Materials mehr Hin- und Herbewegen des Bandes erfordert, wenn Sie mehr Dinge in der Nähe haben. Auf realen Computern wird dies als schlechte Cache-Lokalität bezeichnet.
Gilles 'SO - hör auf böse zu sein'

7

Es ist unmöglich , zwischen ihnen zu unterscheiden. Dies bedeutet, dass der Compiler frei wählen kann, welche Semantik er für eine optimale Leistung für geeignet hält.

Insbesondere werden funktionale Sprachen in der Regel als Wertsemantik beschrieben , da dies unserem konzeptionellen Modell entspricht. Sie werden jedoch häufig mithilfe der Referenzsemantik implementiert , da dies effizienter ist. (Sie müssen nichts kopieren, was nicht geändert werden kann!)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.