0

我正在尝试在 Scala 中使用第一次无标记最终模式并且有点挣扎。

我有以下代数定义:

trait DbSetting[F[_]] {
  def read(url: String, user: String, pw: String): F[DbParameter]
}

trait Environment[F[_]] {
  def get(v: String) : F[Option[String]]
}

和口译员的实施:

final case class DbParameter(url: String, user: String, pw: String)

sealed trait DbError extends NoStackTrace
case object DbSettingError extends DbError


sealed trait DbError extends NoStackTrace
case object DbSettingError extends DbError


// Environment implementation
object Environment {

  def apply[F[_]](implicit ev: Environment[F]): ev.type = ev

  def impl[F[_]: Sync]: Environment[F] = new Environment[F] {
    override def get(v: String): F[Option[String]] =
      Sync[F].delay(sys.env.get(v))
  }
}

// DbSetting implementation
class DbSystemEnvironment[F[_] : MonadError[*, Throwable]] private(env: Environment[F])
  extends DbSetting[F] {
  override def read(url: String, user: String, pw: String): F[DbParameter] = env.get(url)

}

我想做的是,Environment组成DbSystemEnvironment. 这里的问题是,我无法从中获取价值,因为我对inenv.get(url)什么都不知道,除了它是一个. 如何从中获取价值?FDbSystemEnvironmentMonadErrorenv.get(url)::F[Option[String]]

另外,如果在函数中env.get(url)返回,那么它应该返回。NothingreadMonadError

4

1 回答 1

1

如果我正确理解您的问题,您是在询问如何从调用中提取返回值env.get(url),然后将其映射到F[DbParameter].

既然你有MonadError你的,F[_]你应该能够通过做这样的事情很容易地映射结果:

import cats.syntax.flatMap._
import cats.syntax.applicative._
import cats.syntax.applicativeError._

override def read(url: String, user: String, pw: String): F[DbParameter] = 
  env.get(url).flatMap {
    case Some(ev) => DbParameter(ev, user, pw).pure[F]
    case None     => (new Exception("No environment parameter found!")).raiseError[F, DbParameter]
  }
于 2020-06-17T16:18:55.297 回答