如果我有fs2.StreamApp[IO]
,那么在构建主应用流时,如何最好地处理Either
(或\/
)?
例如,我为程序建立了一些输入(因为我喜欢API - 它告诉我"某些内容可能出错"在签名中)。如果有问题,在这种情况下使用命令行参数,我想要从main方法返回一个不同的流。
private def extractArgs(args: List[String]): Error \/ List[_] = args match {
case Nil => CommandLineError().left
case args => args.map(/* whatever */).right
}
当我进入主要方法时......
def stream(args: List[String], requestShutdown: IO[Unit]): Stream[IO, ExitCode] = {
val application: Error \/ Stream[IO, ExitCode] = for {
args <- extractArgs(args)
x <- someOtherEither
} yield Stream.eval(...)
application match {
case -\/(error) => Stream.eval(IO(Log.error(error.message))).flatMap(_ => Stream.emit(ExitCode(1)))
case \/-(ok) => ok
}
}
......一切都变得有点难看。
我可以让析取方法(extractArgs
)只返回错误情况的流,但这似乎很有意思。特别是因为我不知道如何快速失败。
是否有更惯用的方式将左侧变为错误流(在我的情况下打印使用命令然后退出应用程序)?
答案 0 :(得分:0)
我认为来自猫.valueOr
的{{1}}将是一个不错的选择,并且可以考虑更小的功能。
这将产生如下内容:
EitherOps
object Logger {
def error(msg: String): IO[Unit] = IO(Log.error(msg))
}
def runWithArgs(args: List[String]: Error \/ Stream[IO, ExitCode] =
for {
args <- extractArgs(args)
x <- someOtherEither
} yield Stream.eval(...)
def stream(args: List[String], requestShutdown: IO[Unit]): Stream[IO, ExitCode] =
runWithArgs(args) valueOr { error =>
Stream.eval(Logger.error(error.message))
.map(_ => ExitCode(1))
}
的签名是:
.valueOr
您将def valueOr[BB >: B](f: A => BB): BB
和A
设为B
。