如何使用效果类型 IO 的 MonadError?
How to use the MonadError with the effect type IO?
我正在尝试为我的无标记代数编写测试,它使用 MonadError
。
这是带有解释器的无标签代数:
trait DbConnector[F[_]] {
def read(url: DbUrl, user: DbUser, pw: DbPw): F[DbParams]
}
object DbConnector {
def apply[F[_]](implicit dc: DbConnector[F]): dc.type = dc
def impl[F[_] : MonadError[*[_], Throwable]](env: Environment[F])
: DbConnector[F] =
new LiveDbConnector[F](env)
}
和 class 与 Either
的 MonadError
实例的测试:
class DbConnectorSpec extends munit.FunSuite {
test("Environment variables are not set") {
val monadError = MonadError[IO[Either[DbError, DbParams]], DbError]
implicit val badEnv = DbConnector.impl(LiveBadEnvironment())
}
}
代码未编译,因为错误消息:
cats.effect.IO[Either[io.databaker.db.DbError,io.databaker.db.DbParams]] takes no type parameters, expected: 1
[error] val monadErr = MonadError[IO[Either[DbError, DbParams]], DbError]
MonadError
对我来说是新手,这是我第一次尝试使用它。我在 https://www.scalawithcats.com/dist/scala-with-cats.html.
上阅读了 MonadError
的概念
如何制作运行?
考虑MonadError
的类型参数子句
trait MonadError[F[_], E]
请注意 F
和 E
的形状(或种类)不同:
F - a type constructor of * -> * kind
E - a proper type of * kind
类型构造函数和适当类型之间的就像List
和List[Int]
之间的区别,即类型构造函数List
需要一个类型参数 Int
到 构造 一个合适的类型 List[Int]
.
现在考虑那种IO[Either[Throwable,Int]]
scala> :kind -v IO[Either[Throwable, Int]]
cats.effect.IO[Either[Throwable,Int]]'s kind is A
*
This is a proper type.
我们看到它具有正确类型的形状,因此不能代替 F
scala> MonadError[IO[Either[Throwable, Int]], Throwable]
<console>:25: error: cats.effect.IO[Either[Throwable,Int]] takes no type parameters, expected: one
MonadError[IO[Either[Throwable, Int]], Throwable]
现在考虑那种IO
scala> :kind -v IO
cats.effect.IO's kind is F[+A]
* -(+)-> *
This is a type constructor: a 1st-order-kinded type.
我们看到它是一个 * -> *
形状的类型构造函数,它与 F
类型构造函数的形状匹配。因此我们可以写
scala> MonadError[IO, Throwable]
res2: cats.MonadError[cats.effect.IO,Throwable] = cats.effect.IOLowPriorityInstances$IOEffect@75c81e89
Here 是一些进一步的例子
import cats._
import cats.data._
import cats.effect.IO
import cats.instances.either._
import cats.instances.try_._
import cats.instances.future._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.Try
MonadError[Future, Throwable]
MonadError[Try, Throwable]
MonadError[IO, Throwable]
MonadError[Either[String, *], String]
MonadError[EitherT[IO, String, *], String]
MonadError[EitherT[Future, String, *], String]
请注意 Either[String, *]
语法中的 *
来自 并且是使用类型别名转换的替代方法,例如,将 * -> * -> *
kind 转换为所需的 * -> *
亲切
scala> :kind -v Either[String, *]
scala.util.Either[String,?]'s kind is F[+A]
* -(+)-> *
This is a type constructor: a 1st-order-kinded type.
scala> type MyError[+A] = Either[String, A]
defined type alias MyError
scala> :kind -v MyError
MyError's kind is F[+A]
* -(+)-> *
This is a type constructor: a 1st-order-kinded type.
我正在尝试为我的无标记代数编写测试,它使用 MonadError
。
这是带有解释器的无标签代数:
trait DbConnector[F[_]] {
def read(url: DbUrl, user: DbUser, pw: DbPw): F[DbParams]
}
object DbConnector {
def apply[F[_]](implicit dc: DbConnector[F]): dc.type = dc
def impl[F[_] : MonadError[*[_], Throwable]](env: Environment[F])
: DbConnector[F] =
new LiveDbConnector[F](env)
}
和 class 与 Either
的 MonadError
实例的测试:
class DbConnectorSpec extends munit.FunSuite {
test("Environment variables are not set") {
val monadError = MonadError[IO[Either[DbError, DbParams]], DbError]
implicit val badEnv = DbConnector.impl(LiveBadEnvironment())
}
}
代码未编译,因为错误消息:
cats.effect.IO[Either[io.databaker.db.DbError,io.databaker.db.DbParams]] takes no type parameters, expected: 1
[error] val monadErr = MonadError[IO[Either[DbError, DbParams]], DbError]
MonadError
对我来说是新手,这是我第一次尝试使用它。我在 https://www.scalawithcats.com/dist/scala-with-cats.html.
MonadError
的概念
如何制作运行?
考虑MonadError
trait MonadError[F[_], E]
请注意 F
和 E
的形状(或种类)不同:
F - a type constructor of * -> * kind
E - a proper type of * kind
类型构造函数和适当类型之间的List
和List[Int]
之间的区别,即类型构造函数List
需要一个类型参数 Int
到 构造 一个合适的类型 List[Int]
.
现在考虑那种IO[Either[Throwable,Int]]
scala> :kind -v IO[Either[Throwable, Int]]
cats.effect.IO[Either[Throwable,Int]]'s kind is A
*
This is a proper type.
我们看到它具有正确类型的形状,因此不能代替 F
scala> MonadError[IO[Either[Throwable, Int]], Throwable]
<console>:25: error: cats.effect.IO[Either[Throwable,Int]] takes no type parameters, expected: one
MonadError[IO[Either[Throwable, Int]], Throwable]
现在考虑那种IO
scala> :kind -v IO
cats.effect.IO's kind is F[+A]
* -(+)-> *
This is a type constructor: a 1st-order-kinded type.
我们看到它是一个 * -> *
形状的类型构造函数,它与 F
类型构造函数的形状匹配。因此我们可以写
scala> MonadError[IO, Throwable]
res2: cats.MonadError[cats.effect.IO,Throwable] = cats.effect.IOLowPriorityInstances$IOEffect@75c81e89
Here 是一些进一步的例子
import cats._
import cats.data._
import cats.effect.IO
import cats.instances.either._
import cats.instances.try_._
import cats.instances.future._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.Try
MonadError[Future, Throwable]
MonadError[Try, Throwable]
MonadError[IO, Throwable]
MonadError[Either[String, *], String]
MonadError[EitherT[IO, String, *], String]
MonadError[EitherT[Future, String, *], String]
请注意 Either[String, *]
语法中的 *
来自 * -> * -> *
kind 转换为所需的 * -> *
亲切
scala> :kind -v Either[String, *]
scala.util.Either[String,?]'s kind is F[+A]
* -(+)-> *
This is a type constructor: a 1st-order-kinded type.
scala> type MyError[+A] = Either[String, A]
defined type alias MyError
scala> :kind -v MyError
MyError's kind is F[+A]
* -(+)-> *
This is a type constructor: a 1st-order-kinded type.