Ale*_*rab 9 monads scala scalaz
我已经获得了一个java api,用于通过基于回调的样式连接和通过专用总线进行通信.我目前正在scala中实现一个概念验证应用程序,我正在尝试研究如何生成一个稍微更惯用的scala接口.
典型(简化)应用程序在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();
Run Code Online (Sandbox Code Playgroud)
在scala中,我可以明确地定义从(T => Unit)到IListener的隐式转换,这肯定会使事情变得更简单:
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
})
})
Run Code Online (Sandbox Code Playgroud)
看着这个让我想起了scalaz promises和f#async工作流程.
我的问题是:
我可以将其转换为for comprehension或类似的惯用语(我觉得这应该合理地映射到演员)
理想情况下,我希望看到类似的东西:
for(
d <- con.waitForData(DataType.getClass);
val _ = doSomethingWith(d);
o <- con.waitForData(OtherType.getClass)
//etc
)
Run Code Online (Sandbox Code Playgroud)
如果你想使用for
这个理解,我建议你看Scala语言规范如何为内涵扩展到map
,flatMap
等,这会给你这个结构是如何与你已经有了一些线索(嵌套调用addListener
).然后,您可以添加从的返回类型的隐式转换waitForData
调用一个新的类型与合适的map
,flatMap
等方法是委托addListener
.
更新
我想你可以使用scala.Responder[T]
标准库:
假设带有的类addListener
被称为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
})
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以按要求使用此功能
for(
d <- con.waitForData(DataType.getClass);
val _ = doSomethingWith(d);
o <- con.waitForData(OtherType.getClass)
//etc
) ()
Run Code Online (Sandbox Code Playgroud)
有关使用Comet聊天应用程序的信息,请参阅Scala wiki和此演示文稿Responder[T]
.