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