Ad esempio, immaginiamo di avere un messaggio, con l'elenco dei destinatari a cui è stato inviato:
import java.util.Date
case class Message(
text : String,
sent : List[(String, Date)] = Nil
){
def sendTo(address : String) : Message =
Message(text, (address, new Date) :: sent)
override def toString = "Message " + text +
sent.map(s => s._1 + " on " + s._2)
.mkString(" sent to ", ", to ", "")
}
Ora, se volessimo estendere la funzione sendTo in modo da prendere una lista di destinatari a cui inviare il messaggio, con State possiamo fare così:
import scalaz._
import Scalaz._
def sendTo(addresses : List[String])
: State[Message, List[(String, Message)]] =
addresses match {
case head :: tail =>
for( s <- init[Message];
n <- modify[Message]( _ sendTo head ) ;
t <- sendTo(tail)
) yield (head, s sendTo head) :: t
case Nil => state(i => (i, Nil))
}
Questa funzione prende in input la lista di destinatari e ritorna un oggetto che permette di effettuare l'operazione di inviare un messaggio a quei destinatari, ad esempio:
println(
sendTo(List("Onofrio", "Claudia"))
(Message("Hello World!"))
)
che restituisce una tupla contenente il messaggio finale più la lista di tutti i passaggi di stato:
(Message Hello World!
sent to Claudia on Fri Apr 01 23:21:49 CEST 2011,
to Onofrio on Fri Apr 01 23:21:49 CEST 2011,
List((Onofrio, Message Hello World!
sent to Onofrio on Fri Apr 01 23:21:49 CEST 2011),
(Claudia, Message Hello World!
sent to Claudia on Fri Apr 01 23:21:49 CEST 2011,
to Onofrio on Fri Apr 01 23:21:49 CEST 2011)))
Ovviamente, il metodo è deve essere privo di side-effect, altrimenti, poiché viene eseguite più volte gli effetti sono imprevedibili. Per ottenere come side-effect l'invio di una e-mail, per esempio, da quanto ho capito è necessaria la monad Writer. Scriverò un post appena sarò riuscito a farlo con scalaz.
Nessun commento:
Posta un commento