1

如果我有,在构建主应用程序的流时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) 只为错误情况返回一个流,但这似乎很糟糕。特别是因为我也不知道如何快速失败。

有没有更惯用的方法将左转变成错误流(在我的情况下,它会打印一个使用命令然后退出应用程序)?

4

1 回答 1

0

我认为.valueOr从猫中提取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

你在哪里ABas Either[A, B]

于 2018-05-19T21:39:46.323 回答