Domanda

Trovo spesso questo modello nel codice Haskell:

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

...

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

Fondamentalmente, si ha un record di opzioni o qualcosa di simile, che è inizialmente impostato all'inizio del programma.Poiché il programmatore è pigro, non vuole portare il options registra tutto il programma.Egli definisce un MVar per mantenerlo-definito da un brutto uso di unsafePerformIO.Il programmatore assicura, che lo stato è impostato solo una volta e prima di qualsiasi operazione ha avuto luogo.Ora ogni parte del programma deve usare unsafePerformIO ancora una volta, solo per estrarre le opzioni.

A mio parere, tale variabile è considerata pragmaticamente puro (non picchiarmi).Esiste una libreria che astrae questo concetto e assicura che la variabile sia impostata solo una volta, ad es.che nessuna chiamata sia fatta prima di quell'inizializzazione e che non si debba scrivere unsafeFireZeMissilesAndMakeYourCodeUglyAnd DisgustingBecauseOfThisLongFunctionName

È stato utile?

Soluzione

Se stai usando MVar per tenere le impostazioni o qualcosa di simile, perché non provi reader monad?

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

main = runReaderT foo (OptionRecord "foo")

(E lettore normale se non hai bisogno di IO: P)

Altri suggerimenti

Coloro che scambierebbero la trasparenza referenziale essenziale per un po' la convenienza temporanea non merita nessuno dei due purezza né convenienza.

E ' una pessima idea.Il codice in cui lo trovi è un codice errato.*

Non c'è modo di avvolgere completamente questo modello in modo sicuro, perché non è un modello sicuro.Non farlo nel tuo codice.Non cercare un modo sicuro per farlo.Non c'è un modo sicuro per farlo.Metti il unsafePerformIO giù sul pavimento, lentamente, e indietro lontano dalla console...

*Ci sono motivi legittimi per cui le persone usano MVAR di alto livello, ma questi motivi hanno a che fare con i binding al codice straniero per la maggior parte, o alcune altre cose in cui l'alternativa è molto disordinata.In questi casi, per quanto ne so, tuttavia, gli MVAR di livello superiore sono non accesso da dietro unsafePerformIO.

Utilizzare parametri impliciti.Sono leggermente meno pesanti di ogni funzione Reader o ReaderT nel suo tipo.Devi cambiare le firme di tipo delle tue funzioni, ma penso che un tale cambiamento possa essere scritto.(Sarebbe una bella caratteristica per un IDE Haskell.)

C'è una ragione importante per non usare questo modello.Per quanto ne so, in

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

Haskell non garantisce che options saranno valutati una sola volta.Poiché il risultato di option è un valore puro, può essere memoizzato e riutilizzato, ma può anche essere ricalcolato per ogni chiamata (es.inlined) e il significato del programma non deve cambiare (contrariamente al tuo caso).

Se decidi ancora di utilizzare questo modello, assicurati di aggiungere {-# NOINLINE options #-}, altrimenti potrebbe ottenere inlined e il Suo programma fallirà!(E con questo stiamo uscendo dalle garanzie date dal linguaggio e dal sistema di tipi e facendo affidamento esclusivamente sull'implementazione di un particolare compilatore.)

Questo argomento è stato ampiamente discusso e le possibili soluzioni sono ben riassunte su Haskell Wiki in Stato mutabile di livello superiore.Attualmente non è possibile astrarre in modo sicuro questo modello senza un ulteriore supporto del compilatore.

Trovo spesso questo modello nel codice Haskell:

Leggi codice diverso.

Poiché il programmatore è pigro, non vuole portare il record di opzioni su tutto il programma.Definisce un MVar per mantenerlo-definito da un brutto uso di unsafePerformIO.Il programmatore assicura, che lo stato è impostato solo una volta e prima di qualsiasi operazione ha avuto luogo.Ora ogni parte del programma deve usare di nuovo unsafePerformIO, solo per estrarre le opzioni.

Sembra letteralmente esattamente ciò che la monade del lettore realizza, tranne che la monade del lettore lo fa in modo sicuro.Invece di accogliere la tua pigrizia, scrivi solo un buon codice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top