10

我无法运行一个简单的 scalaz-stream 示例,从 TCP 读取并写入标准输出。

val src = tcp.reads(1024)
val addr = new InetSocketAddress(12345)
val p = tcp.server(addr, concurrentRequests = 1) {
  src ++ tcp.lift(io.stdOutLines)
}
p.run.run

它只是坐在那里,不打印任何东西。

我也尝试过各种安排使用to, 总是用tcp.lift咒语来获得 a Process[Connection, A],包括

tcp.server(addr, concurrentRequests = 1)(src) map (_ to tcp.lift(io.stdOutLines))

这甚至不编译。

我需要wye将源流和打印流放在一起吗?我在原始拉取请求中找到的一个tcp示例nio似乎表明了这一点,但似乎wye不再存在于 上Process,因此不幸的是,混乱盛行。


编辑事实证明,除了 Paul 解释的类型问题之外,您还需要“手动”运行内部进程,例如通过执行p.map(_.run.run).run.run. 我不认为这是这样做的惯用方式,但它确实有效。

4

1 回答 1

5

你需要src穿过水槽才能真正写出任何东西。我认为应该这样做:

import scalaz.stream.{io,tcp,text}
import scalaz.stream.tcp.syntax._

val p = tcp.server(addr, concurrentRequests = 1) { 
  tcp.reads(1024).pipe(text.utf8Decode) through tcp.lift(io.stdOutLines) 
}
p.run.run

该表达式src ++ tcp.lift(io.stdOutLines)实际上应该是一个类型错误。的类型tcp.reads(1024)Process[Connection,ByteVector],的类型tcp.lift(io.stdOutLines)Process[Connection, String => Task[Unit]]。附加这两个进程没有意义,它类型检查的唯一原因是由于Process[+F[_],+O]. Any当您附加两个具有不相关输出类型的进程时,Scala 会“有用”地进行推断。

scalaz-stream 的未来版本可能会在++其他函数上添加一个约束,这些函数利用协方差来确保计算出的最小上限不是像Anyor那样无用的东西Serializable。这将大大有助于防止此类错误。同时,确保您了解您正在使用的所有功能的类型、它们的作用以及如何将它们组合在一起。

于 2014-12-17T17:59:18.417 回答