Generieren Sie eine zufällige Zeichenfolge zur Kompilierzeit oder Laufzeit und verwenden Sie sie im Rest des Programms

8

Was wäre der beste Weg, dies zu tun? %Code%? Vorlage Haskell? Etwas anderes? Ich habe noch nie eines von beiden benutzt, daher kenne ich nicht viele Details, sie zu benutzen.

Beachten Sie, dass das Programm jedes Mal kompiliert wird, wenn es ausgeführt wird. Es spielt also keine Rolle, ob ich die Zeichenfolge zum Zeitpunkt der Kompilierung oder zur Laufzeit erzeuge. Ich muss diese Zeichenkette auch in Tonnen von Stellen im Code verwenden, so dass ich es nicht wirklich "richtig" machen kann und dass es eine IO-Aktion wäre, die viel zu viel anderen Code benötigt, um in die IO-Monade eingefügt zu werden .

    
Drew 06.07.2013, 06:03
quelle

5 Antworten

4

Die Verwendung von unsafeperformIO in diesem speziellen Fall scheint in Ordnung zu sein, wie in der Dokumentation steht:

  

Damit dies sicher ist, sollte die IO-Berechnung frei von Nebenwirkungen sein   und unabhängig von seiner Umgebung.

Wir sind nicht besorgt über die Reihenfolge von newStdGen .

%Vor%     
Ankur 06.07.2013, 06:37
quelle
10

Ich würde nicht empfehlen, unsafePerformIO zu verwenden. Ich nehme an, dass der Haskell-Bericht nicht besagt, dass eine konstante Funktion Memo ist, so dass es passieren kann,

%Vor%

gibt Ihnen unterschiedliche Ergebnisse für verschiedene Anrufe! Mit GHC wird es höchstwahrscheinlich gemerkt, aber ohne Garantien. Zum Beispiel, was ist, wenn der Compiler die Funktion einfügt? (GHC ist wahrscheinlich schlau genug, es nicht zu tun, aber wieder, keine Garantien ...). Und zum Beispiel

%Vor%

wird Ihnen definitiv jedes Mal andere Ergebnisse geben, wenn es aufgerufen wird.

Ich würde lieber mit Template Haskell gehen. Es ist vielleicht ein bisschen komplizierter, aber sicher. In einem Modul definieren wir

%Vor%

(Vielleicht könnte randStringD lesbarer geschrieben werden - wenn Sie eine Idee haben, bearbeiten Sie sie bitte oder kommentieren Sie sie.)

Dann können wir es in einem anderen Modul verwenden, um eine konstante Funktion mit einem gegebenen Namen zu deklarieren:

%Vor%     
Petr Pudlák 06.07.2013 07:59
quelle
8
___ answer17500975 ___

Ich würde nicht empfehlen, main zu verwenden. Ich nehme an, dass der Haskell-Bericht nicht besagt, dass eine konstante Funktion Memo ist, so dass es passieren kann,

%Vor%

gibt Ihnen unterschiedliche Ergebnisse für verschiedene Anrufe! Mit GHC wird es höchstwahrscheinlich gemerkt, aber ohne Garantien. Zum Beispiel, was ist, wenn der Compiler die Funktion einfügt? (GHC ist wahrscheinlich schlau genug, es nicht zu tun, aber wieder, keine Garantien ...). Und zum Beispiel

%Vor%

wird Ihnen definitiv jedes Mal andere Ergebnisse geben, wenn es aufgerufen wird.

Ich würde lieber mit Template Haskell gehen. Es ist vielleicht ein bisschen komplizierter, aber sicher. In einem Modul definieren wir

%Vor%

(Vielleicht könnte rstr lesbarer geschrieben werden - wenn Sie eine Idee haben, bearbeiten Sie sie bitte oder kommentieren Sie sie.)

Dann können wir es in einem anderen Modul verwenden, um eine konstante Funktion mit einem gegebenen Namen zu deklarieren:

%Vor%     
___ qstntxt ___

Was wäre der beste Weg, dies zu tun? %Code%? Vorlage Haskell? Etwas anderes? Ich habe noch nie eines von beiden benutzt, daher kenne ich nicht viele Details, sie zu benutzen.

Beachten Sie, dass das Programm jedes Mal kompiliert wird, wenn es ausgeführt wird. Es spielt also keine Rolle, ob ich die Zeichenfolge zum Zeitpunkt der Kompilierung oder zur Laufzeit erzeuge. Ich muss diese Zeichenkette auch in Tonnen von Stellen im Code verwenden, so dass ich es nicht wirklich "richtig" machen kann und dass es eine IO-Aktion wäre, die viel zu viel anderen Code benötigt, um in die IO-Monade eingefügt zu werden .

    
___ answer17500411 ___

Die Verwendung von Reader in diesem speziellen Fall scheint in Ordnung zu sein, wie in der Dokumentation steht:

  

Damit dies sicher ist, sollte die IO-Berechnung frei von Nebenwirkungen sein   und unabhängig von seiner Umgebung.

Wir sind nicht besorgt über die Reihenfolge von Reader r a .

%Vor%     
___ answer17503580 ___

Das Generieren einer Zufallszahl in MonadReader r m => m a impliziert nicht, dass Downstream-Funktionen ask verwenden müssen.

Hier ist eine reine Beispielfunktion, die von einem Wert vom Typ r abhängt:

%Vor%

... und hier ist eine Aktion (r ->) , die ein MonadReader r erzeugt:

%Vor%

Ich muss f :: Int -> Int -> String -> Int nicht ändern, um runReader zu verwenden. Stattdessen verwende ich FlexibleContexts :

%Vor%

Dies ist genau die Art von Problem, das Funktoren lösen sollen: das Heben von Morphismen über umbrochene Werte, so dass die Morphismen nicht modifiziert werden müssen.

    
___ tag123io ___ Bei der Berechnung bezieht sich die Eingabe / Ausgabe oder E / A auf die Kommunikation zwischen einem Informationsverarbeitungssystem (z. B. einem Computer) und der Außenwelt, möglicherweise einem Menschen, oder einem anderen Informationsverarbeitungssystem. ___ tag123haskell ___ Haskell ist eine funktionale Programmiersprache mit starker statischer Typisierung, verzögerungsfreier Auswertung, umfangreicher Parallelitäts- und Parallelitätsunterstützung und einzigartigen Abstraktionsfunktionen. ___ answer17500261 ___
%Vor%

Dies erzeugt eine Zeichenfolge mit zehn Zeichen Länge und nur Kleinbuchstaben. Dieser Code ist in der IO-Monade, aber str ist rein, er kann an reine Funktionen übergeben werden. Ohne die IO-Monade können Sie nichts Zufälliges bekommen. Du könntest einen unsicheren PerformIO machen, aber ich verstehe nicht warum. Sie können den Wert str übergeben, wenn Sie immer den gleichen möchten. Wenn Sie sich die letzte Zeile meines Codes anschauen, können Sie sehen, dass ich eine reine Funktion habe, die auf der Zeichenkette operiert, aber da ich sie sehen möchte, rufe ich String -> Int auf, was eine leere IO Aktion zurückgibt.

EDIT: Oder dies könnte der Ort für die Reader Monade

sein     
___ tag123templatehaskell ___ Template Haskell ist eine GHC-Erweiterung von Haskell, die Metaprogrammierungsfunktionen zur Kompilierungszeit hinzufügt. Dies ermöglicht Benutzern, Programme zu schreiben, die ihr Programm zur Kompilierzeit erzeugen oder modifizieren: eine Form von Kompilierzeit-Makros. ___ tag123unsafeeperformio ___ Dieses Tag ist für Fragen bezüglich der Funktion 'unsafePerformIO' in Haskell und Scala, mit der Sie beliebige IO innerhalb eines reinen Ausdrucks ausführen können. ___ qstnhdr ___ Generieren Sie eine zufällige Zeichenfolge zur Kompilierzeit oder Laufzeit und verwenden Sie sie im Rest des Programms ___
Antal Spector-Zabusky 06.07.2013 07:35
quelle
4

Das Generieren einer Zufallszahl in IO impliziert nicht, dass Downstream-Funktionen IO verwenden müssen.

Hier ist eine reine Beispielfunktion, die von einem Wert vom Typ A abhängt:

%Vor%

... und hier ist eine Aktion IO , die ein A erzeugt:

%Vor%

Ich muss f nicht ändern, um IO zu verwenden. Stattdessen verwende ich fmap :

%Vor%

Dies ist genau die Art von Problem, das Funktoren lösen sollen: das Heben von Morphismen über umbrochene Werte, so dass die Morphismen nicht modifiziert werden müssen.

    
Gabriel Gonzalez 06.07.2013 13:46
quelle
1
%Vor%

Dies erzeugt eine Zeichenfolge mit zehn Zeichen Länge und nur Kleinbuchstaben. Dieser Code ist in der IO-Monade, aber str ist rein, er kann an reine Funktionen übergeben werden. Ohne die IO-Monade können Sie nichts Zufälliges bekommen. Du könntest einen unsicheren PerformIO machen, aber ich verstehe nicht warum. Sie können den Wert str übergeben, wenn Sie immer den gleichen möchten. Wenn Sie sich die letzte Zeile meines Codes anschauen, können Sie sehen, dass ich eine reine Funktion habe, die auf der Zeichenkette operiert, aber da ich sie sehen möchte, rufe ich putStrLn auf, was eine leere IO Aktion zurückgibt.

EDIT: Oder dies könnte der Ort für die Reader Monade

sein     
DiegoNolan 06.07.2013 06:15
quelle