2014-09-04 10 views
5

immaginare una funzione:interni caching con una funzione parzialmente applicata

bar :: Foo -> A -> B -> C -> IO() 

Tale funzione esegua alcune IO roba utilizzando una Foo ed altri valori. Il valore Foo deve essere passato a bar, e può essere recuperato da IO tramite questo:

foo :: X -> IO Foo 

Ora, A, B, C e X sono tutti pianura valori puri. Preferirei piace una tale funzione bar:

bar :: X -> A -> B -> C -> IO() 

E Foo sarebbe generato nella funzione bar utilizzando il valore X. Se lo faccio:

let f = bar myX 

f :: A -> B -> C -> IO(). Se chiamo più volte questa funzione, il valore X rimane lo stesso a causa dell'applicazione parziale, ma poiché si tratta di un effetto IO, verrà generato ogni volta. C'è una nativo, built-in-GHC modo per eseguire un qualche tipo di caching in modo che il valore Foo viene generato una volta - per la chiusura generato? Immagino che sia tutto legato al pugilato, ma non ho mai capito come farlo senza usare lo sporco IORef, espandendo i parametri di bar, che è brutto.

risposta

12

Quello che stai chiedendo letteralmente spezzerebbe la trasparenza referenziale, un grande "no" in Haskell. Quindi questo mi lascia con la domanda, dovrei mostrarti il ​​tipo di metodo unsafeLaunchMissiles che fa (a volte, se sei fortunato e le ottimizzazioni non lo infrangono) quello che chiedi letteralmente ma è molto scoraggiato, o dovrei mostrare il modo pulito che cambia i tipi solo un po '? Lasciami provare quest'ultimo.

Se fate la vostra bar hanno il seguente tipo invece:

bar :: X -> IO (A -> B -> C -> IO()) 

quindi è possibile utilizzare, in un blocco do:

f <- bar myX 

In alternativa, se si pensa che non trova la punto di ridefinire bar per prendere un X, quindi conservare il primo tipo per bar e fare

f <- bar =<< foo myX 
+1

Sì, conosco le funzioni 'unsafeScheisse', non lo voglio. La tua soluzione mi fa pensare a qualcosa che uso spesso, come la funzione passata a 'control'. Mi piace, sembra promettente. – phaazon

Problemi correlati