delimited-continuations

___ qstnhdr ___ Cont monad shift ___ tag123haskell ___ Haskell ist eine funktionale Programmiersprache mit starker statischer Typisierung, verzögerungsfreier Auswertung, umfangreicher Parallelitäts- und Parallelitätsunterstützung und einzigartigen Abstraktionsfunktionen. ___ qstntxt ___

Während ich versuchte, etwas Intuition für den ContT-Monade-Transformer aufzubauen, fand ich mich (vielleicht nicht überraschend) verwirrt. Das Problem liegt in der shiftT-Operation, die nichts Nützliches zu tun scheint.

Zuerst ein einfaches Beispiel, wie man es benutzen könnte

%Vor%

%code% könnte ein etwas komplexerer Ausdruck sein, solange er %code% zurückgibt. Nun, ein Versuch, meine Intuition zu erklären, dass shiftT ist, fügt nichts hinzu:

%Vor%

Es stellte sich heraus, dass wir ContT direkt erstellen könnten.

Fragestunde: Gibt es eine Situation, in der shift / shiftT etwas über cont / ContT hinzufügt? Oder werden sie nur verwendet, um den Code lesbarer zu machen?

    
___ tag123limitierteKontinuationen ___ Eine begrenzte Folge ist eine "Scheibe" eines Folgerahmens, der zu einer Funktion verdinglicht wurde ___ tag123continuations ___ In der Informatik und Programmierung ist eine Fortsetzung eine abstrakte Darstellung des Kontrollzustandes. Eine Fortsetzung bestätigt eine Instanz eines Berechnungsprozesses an einem gegebenen Punkt der Prozessausführung. Es enthält Informationen wie den aktuellen Stapel des Prozesses (einschließlich aller Daten, deren Lebensdauer innerhalb des Prozesses liegt, beispielsweise "lokale Variablen") sowie den Punkt des Prozesses bei der Berechnung. ___ answer43697115 ___

Nach dem Suche Github von gurkenglas 's Rat, den ich diese sehr schöne Erklärung von %code% und %code% mit Anwendungsbeispielen, Motivation und Semantik!

Diese Funktionen sind sehr einfach. Ihre Definition in %code% Bibliothek ist einfach:

%Vor%

Aber Philosophie und Bedeutung liegen weit hinter einem intuitiven Verständnis. Daher empfehle ich Ihnen, die Erklärung über den obigen Link zu lesen. Manchmal passiert es, dass Dinge, die einfach zu definieren sind, etwas Komplexes tun können.

Angepasste Dokumentation aus der Erklärung in oben verlinkten Pugs:

  

%code%

     

%code% ist wie %code% , außer dass Sie die Fortsetzung aktivieren   von %code% zur Verfügung gestellt, wird es bis zum Ende des nächsten einschließenden %code% laufen,   Springe dann zurück zu dem Punkt, an dem du die Fortsetzung aktiviert hast.   Beachten Sie, dass die Kontrolle schließlich zu dem Punkt nach dem zurückkehrt   Subkontinuation ist aktiviert, Sie können es mehrmals in der aktivieren   gleicher Block. Dies ist anders als in den Fortsetzungen von %code% , die den aktuellen Wert verwerfen   Ausführungspfad bei Aktivierung.

     

Siehe %code% für ein Beispiel, wie diese Begrenzungsunterteilungen tatsächlich aussehen   arbeiten.

     

%code%

     

Erstellen Sie einen Gültigkeitsbereich, für den %code% die letzten Unterteilungen garantiert   Beenden Sie das Ende von. Betrachten Sie dieses Beispiel:

%Vor%      

Dies wird:

     
  1. Führe %code%

  2. aus   
  3. Führe %code%

  4. aus   
  5. Führe %code%

  6. aus   
  7. Binden Sie %code% an 1 und führen Sie daher %code%

  8. aus   
  9. Fällt vom Ende von %code% und springt direkt nach %code%

  10. zurück   
  11. Führe %code%

  12. aus   
  13. Binden Sie %code% an 2 und führen Sie daher %code%

  14. aus   
  15. Fällt vom Ende von %code% und springt direkt nach %code%

  16. zurück   
  17. Escape von %code% , was dazu führt, dass es 0 ergibt

  18.   

Im Gegensatz zu den Fortsetzungen von %code% werden diese Unterkontinuationen schließlich   zurück zum Punkt, nachdem sie aktiviert wurden, nachdem sie vom Ende des   nächste %code% .

    
___ answer43710915 ___

Sie haben Recht, dass Fortsetzungen begrenzt undefinierten oder unzureichend abgegrenzten Fortsetzungen mit ausgedrückt werden kann. Daher können die Definitionen von %code% und %code% immer nur mit %code% beschrieben werden. Aber:

  • Getrennte Fortsetzungen sind weniger leistungsstark . Dies macht es einfacher für Menschen zu implementieren und auch zu argumentieren. (Siehe auch viele andere interessante Beiträge über Fortsetzungen von Oleg Kiselyov ).
  • Die Verwendung der bekannten Notation shift / reset erleichtert das Verständnis, insbesondere für diejenigen, die mit dem Konzept vertraut sind.

Im Wesentlichen ermöglichen Fortsetzungen, ein Programm umzudrehen: Der durch %code% abgegrenzte Block wird innerhalb des inneren Teils des Programms gequetscht, wenn %code% die übergebene Funktion aufruft. (Im Falle von undefinierten Fortsetzungen ist der gesamte Ausführungskontext drinnen gedrängt, was sie so komisch macht.)

Lassen Sie uns ein paar Beispiele machen:

%Vor%

Wenn wir %code% ohne %code% haben, ist es nur eine reine Berechnung, nichts Besonderes. Die obige Funktion gibt einfach %code% zurück.

Nun können wir beide verwenden:

%Vor%

Das wird interessanter. Der Code zwischen %code% und %code% wird tatsächlich in die Aufrufe von %code% gedrückt, in diesem einfachen Beispiel ist es nur %code% . Wenn wir %code% aufrufen, wird die gesamte Berechnung durchgeführt und ihr Ergebnis wird das Ergebnis des Aufrufs %code% . Wir machen das zweimal, also rufen wir im Wesentlichen alles zwischen %code% und %code% zweimal auf. Und das Ergebnis der gesamten Berechnung ist %code% , das Ergebnis des Aufrufs %code% .

So in einem Sinn, der %code% Block wird der äußere Teil der Berechnung und der Block zwischen %code% und %code% wird der innere Teil der Berechnung.

So weit, so gut. Aber es wird noch entmutigender, wenn wir %code% zweimal aufrufen, wie in diesem Codebeispiel:

%Vor%

Und hier ist, was es produziert (versteckt für diejenigen, die versuchen wollen, es als Übung herauszufinden):

  

%code%

Nun passiert das Programm zweimal :

  1. Zuerst ist alles außerhalb des Blocks %code% an den Aufruf %code% gebunden, einschließlich des nächsten %code% . Und das Ergebnis der Berechnung ist das Ergebnis des Blocks %code% .
  2. Zweitens, wenn die zweite %code% in %code% aufgerufen wird, ist der Rest der Berechnung wiederum an den Aufruf %code% gebunden. Und das Ergebnis dieser inneren Berechnung ist das Ergebnis des Blocks %code% .

Also lassen wir in %code% den Rest der Berechnung für jedes der drei Argumente laufen, und während jedes von ihnen machen wir eine ähnliche Sache für jedes der anderen drei Argumente. Das Ergebnis ist dann das kartesische Produkt der beiden Listen, da wir im Wesentlichen zwei verschachtelte Schleifen durchgeführt haben.

Das gleiche gilt für %code% und %code% , nur mit zusätzlichen Nebenwirkungen. Wenn wir zum Beispiel debuggen wollen, was tatsächlich passiert, können wir den obigen Code in den %code% monad- und print-Debugging-Anweisungen ausführen:

%Vor%     
___
2
Antworten

Cont monad shift

Während ich versuchte, etwas Intuition für den ContT-Monade-Transformer aufzubauen, fand ich mich (vielleicht nicht überraschend) verwirrt. Das Problem liegt in der shiftT-Operation, die nichts Nützliches zu tun scheint. Zuerst ein einfaches...
29.04.2017, 12:20