Frage

Ich finde dieses Muster oft im Haskell-Code:

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

...

doSomething :: Foo -> Bar
doSomething = unsafePerformIO $ do
  opt <- readMVar options
  doSomething' where ...

Grundsätzlich verfügt man über eine Liste von Optionen oder Ähnlichem, die zunächst zu Beginn des Programms festgelegt wird.Da der Programmierer faul ist, möchte er das nicht tragen options Aufnahme während des gesamten Programms.Er definiert eine MVar es behalten – definiert durch eine hässliche Verwendung von unsafePerformIO.Der Programmierer stellt sicher, dass der Zustand nur einmal und vor jeder Operation gesetzt wird.Jetzt muss jeder Teil des Programms verwendet werden unsafePerformIO Nochmals, nur um die Optionen zu extrahieren.

Meiner Meinung nach wird eine solche Variable berücksichtigt pragmatisch rein (Schlag mich nicht).Gibt es eine Bibliothek, die dieses Konzept abstrahiert und sicherstellt, dass die Variable nur einmal gesetzt wird, d. h.dass vor dieser Initialisierung kein Aufruf erfolgt und dass man nicht schreiben muss unsafeFireZeMissilesAndMakeYourCodeUglyAnd DisgustingBecauseOfThisLongFunctionName

War es hilfreich?

Lösung

Wenn Sie MVar zum Halten von Einstellungen oder ähnlichem verwenden, warum versuchen Sie es nicht mit Reader Monad?

foo :: ReaderT OptionRecord IO ()
foo = do
    options <- ask
    fireMissiles

main = runReaderT foo (OptionRecord "foo")

(Und regulärer Reader, wenn Sie kein IO benötigen :P)

Andere Tipps

Diejenigen, die eine wesentliche Referenztransparenz für ein wenig vorübergehende Bequemlichkeitsmöglichkeiten verdienen, verdienen weder Reinheit noch Bequemlichkeit.

Das ist eine schlechte Idee.Der Code, in dem Sie dies finden, ist fehlerhafter Code.*

Es gibt keine Möglichkeit, dieses Muster vollständig sicher abzuschließen, da es kein sicheres Muster ist.Tun Sie dies nicht in Ihrem Code.Suchen Sie nicht nach einem sicheren Weg, dies zu tun.Es gibt keinen sicheren Weg, dies zu tun.Lege das unsafePerformIO Lassen Sie sich langsam auf den Boden fallen und entfernen Sie sich von der Konsole ...

*Es gibt legitime Gründe dafür, dass Leute MVars der obersten Ebene verwenden, aber diese Gründe haben größtenteils mit Bindungen an fremden Code oder ein paar anderen Dingen zu tun, bei denen die Alternative sehr chaotisch ist.In diesen Fällen sind es meines Wissens jedoch die MVars der obersten Ebene nicht von hinten zugänglich unsafePerformIO.

Verwenden Sie implizite Parameter.Sie sind etwas weniger schwer als die Herstellung aller Funktionen Reader oder ReaderT in seiner Art.Sie müssen zwar die Typsignaturen Ihrer Funktionen ändern, aber ich denke, eine solche Änderung kann per Skript erfolgen.(Wäre eine nette Funktion für eine Haskell-IDE.)

Es gibt einen wichtigen Grund, dieses Muster nicht zu verwenden.Soweit ich weiß, in

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

Haskell gibt hierfür keine Garantie options wird nur einmal ausgewertet.Da das Ergebnis von option Da es sich um einen reinen Wert handelt, kann er gespeichert und wiederverwendet, aber auch für jeden Aufruf neu berechnet werden (d. h.inlined) und die Bedeutung des Programms darf sich nicht ändern (im Gegensatz zu Ihrem Fall).

Wenn Sie sich dennoch für die Verwendung dieses Musters entscheiden, unbedingt hinzufügen {-# NOINLINE options #-}, sonst könnte es inline werden und Ihr Programm schlägt fehl!(Und dadurch verlassen wir die Garantien der Sprache und des Typsystems und verlassen uns ausschließlich auf die Implementierung eines bestimmten Compilers.)

Dieses Thema wurde ausführlich diskutiert und mögliche Lösungen sind im Haskell Wiki in gut zusammengefasst Änderbarer Zustand der obersten Ebene.Derzeit ist es nicht möglich, dieses Muster ohne zusätzliche Compilerunterstützung sicher zu abstrahieren.

Ich finde dieses Muster oft im Haskell-Code:

Anderen Code lesen.

Da der Programmierer faul ist, möchte er den Optionsdatensatz nicht über das gesamte Programm verteilen.Er definiert eine MVar, um sie zu behalten – definiert durch eine hässliche Verwendung von unsafePerformIO.Der Programmierer stellt sicher, dass der Zustand nur einmal und vor jeder Operation gesetzt wird.Jetzt muss jeder Teil des Programms erneut unsafePerformIO verwenden, nur um die Optionen zu extrahieren.

Klingt im wahrsten Sinne des Wortes nach genau dem, was die Lesermonade erreicht, außer dass die Lesermonade es auf sichere Weise tut.Anstatt Ihrer eigenen Faulheit Rechnung zu tragen, schreiben Sie einfach wirklich guten Code.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top