In realtà non avete cortocircuitato nulla. Stai ancora eseguendo gli IO; semplicemente non catturi i valori.
Inoltre, la monade IO standard non definisce filter
(o withFilter
), quindi non è possibile utilizzare le protezioni nella propria comprensione.
Ora, se si desidera solo quello che hai detto (stessa logica, solo più DRY), si può sempre assegnare una variabile temporanea nella per la comprensione:
for {
a <- io
b <- shortCircuit(io, a == 1)
continue = b.map(_ == 1).getOrElse(false)
c <- shortCircuit(io, continue)
d <- shortCircuit(io, continue)
e <- shortCircuit(io, continue)
} yield …
Ma se si vuole realmente breve -circuito, dovrai rompere i casi in qualche modo. Ecco una possibilità, supponendo che si desidera solo per impacchettare tutto in un array in modo che il tipo di ritorno è semplice, e il tuo compagno oggetto IO
ha un metodo di applicazione che è possibile utilizzare per creare qualcosa che solo restituisce un valore:
io.flatMap(a =>
if (a == 1) IO(() => Array(a))
else io.flatMap(b =>
if (b == 1) IO(() => Array(a,b))
else for {
c <- io
d <- io
e <- io
} yield Array(a,b,c,d,e)
)
)
Se i tipi di reso sono più complicati, potrebbe essere necessario lavorare di più con i tipi di specifica.
FWIW, vale la pena notare la sanzione che si paga per mantenere le cose avvolte nelle monadi; senza, la stessa logica sarebbe (per esempio):
io() match {
case 1 => Array(1)
case a => io() match {
case 1 => Array(a, 1)
case b => Array(a, b, io(), io(), io())
}
}
E se permettete ritorni, si ottiene:
val a = io()
if (a == 1) return Array(a)
val b = io()
if (b == 1) return Array(a, b)
Array(a, b, io(), io(), io())
E 'anche possibile in linea di principio per decorare la monade IO con metodi aggiuntivi che aiutano un po ', ma lo standard withFilter
non funzionerà, quindi non sarà possibile utilizzare lo zucchero sintattico per la comprensione.
Hai bisogno dei valori di 'a',' b', 'c', ecc., O ti interessano solo gli effetti? 'OptionT [IO,?]' Tipo di suoni come quello che stai cercando, ma ti darebbe un 'None 'se questo cortocircuiti. –
Ho bisogno di questi valori: come condizione per il cortocircuito e anche nella clausola yield. –
io ha un effetto collaterale, quindi il metodo run può restituire un valore diverso dopo ogni chiamata. –