Can I transform this asynchronous java network API into a monadic representation (or something else idiomatic)?
monads, scala, scalaz
Solution
If you want to use a `for` comprehension for this, I'd recommend looking at the Scala Language Specification for how for comprehensions are expanded to `map`, `flatMap`, etc. This will give you some clues about how this structure relates to what you've already got (with nested calls to `addListener`). You can then add an implicit conversion from the return type of the `waitForData` call to a new type with the appropriate `map`, `flatMap`, etc methods that delegate to `addListener`.
Update
I think you can use `scala.Responder[T]` from the standard library:
Assuming the class with the `addListener` is called `Dispatcher[T]`:
trait Dispatcher[T] {
def addListener(listener: IListener[T]): Unit
}
trait IListener[T] {
def onEvent(t: T): Unit
}
implicit def dispatcher2Responder[T](d: Dispatcher[T]):Responder[T] = new Responder[T} {
def respond(k: T => Unit) = d.addListener(new IListener[T] {
def onEvent(t:T) = k
})
}
You can then use this as requested
for(
d <- con.waitForData(DataType.getClass);
val _ = doSomethingWith(d);
o <- con.waitForData(OtherType.getClass)
//etc
) ()
See the Scala wiki and this presentation on using `Responder[T]` for a Comet chat application.
Problem
I've been given a java api for connecting to and communicating over a proprietary bus using a callback based style. I'm currently implementing a proof-of-concept application in scala, and I'm trying to work out how I might produce a slightly more idiomatic scala interface. A typical (simplified) application might look something like this in Java: ``` DataType type = new DataType(); BusConnector con = new BusConnector(); con.waitForData(type.getClass()).addListener(new IListener<DataType>() { public void onEvent(DataType t) { //some stuff happens in here, and then we need some more data con.waitForData(anotherType.getClass()).addListener(new IListener<anotherType>() { public void onEvent(anotherType t) { //we do more stuff in here, and so on } }); } }); //now we've got the behaviours set up we call con.start(); ``` In scala I can obviously define an implicit conversion from (T => Unit) into an IListener, which certainly makes things a bit simpler to read: ``` implicit def func2Ilistener[T](f: (T => Unit)) : IListener[T] = new IListener[T]{ def onEvent(t:T) = f } val con = new BusConnector con.waitForData(DataType.getClass).addListener( (d:DataType) => { //some stuff, then another wait for stuff con.waitForData(OtherType.getClass).addListener( (o:OtherType) => { //etc }) }) ``` Looking at this reminded me of both scalaz promises and f# async workflows. My question is this: Can I convert this into either a for comprehension or something similarly idiomatic (I feel like this should map to actors reasonably well too) Ideally I'd like to see something like: ``` for( d <- con.waitForData(DataType.getClass); val _ = doSomethingWith(d); o <- con.waitForData(OtherType.getClass) //etc ) ```