在scalaz`\/`中转换`Option [Tuple]`

sim*_*mao 4 scala scalaz

我试图从一个连接创建一个连接Option[Tuple],并在析取中返回结果,但我的代码看起来有点奇怪:

  def ssh(config: GushConfig): \/[Throwable, Client] = {
    val params = for {
      host <- config.mysqlHost
      port <- config.mysqlPort
      user <- config.mysqlUser
      password <- config.mysqlPassword
      sshAddress <- config.sshTunnelAddress
      sshTunnelUser <- config.sshTunnelUser
    } yield (host, port, user, password, sshAddress, sshTunnelUser)

    params match {
      case Some((host, port, user, password, sshAddress, sshTunnelUser)) ?
        Try({
          // Do stuff that can fail and throw exceptions

          new Client("127.0.0.1", lport, user, password)
        }) match {
          case Success(v) ? v.right
          case Failure(t) ? t.left
        }
      case None ?
        new Exception("Not enough parameters to initialize a ssh client").left
    }
  }
Run Code Online (Sandbox Code Playgroud)

我首先需要模式匹配我的第一个Option检查我有所有必需的选项,然后如果我这样做,尝试连接内部a Try 然后将try的结果转换为析取.

有没有更好的方法来进行这种转变?

lmm*_*lmm 6

您可能希望将它们转换为相同的类型 - 您可以使用.toRightDisjunctionOption,并且您可以Try使用scala.util.control.Exception相反的方式来执行此操作:

import scala.util.control.Exception._

for {
  params_ ? params.toRightDisjunction(
    new Exception("Not enough parameters to initialize a ssh client"))
  (host, port, user, password, sshAddress, sshTunnelUser) = params_
  v ? catching(classOf[Exception]) either functionThatCouldThrow() disjunction
} yield v
Run Code Online (Sandbox Code Playgroud)

您也可以Option使用.sequence而不是显式for/ yield(这可能需要shapeless-scalaz)来做最初的事情:

params = (config.mysqlHost, config.mysqlPort, ...).sequence
Run Code Online (Sandbox Code Playgroud)