使用 Scala-cats 隐式解析
Implicits resolution with Scala-cats
例子取自Tagless Final in Mastering Functional Programming:
trait Capabilities[F[_]] {
def resource(name: String): F[String]
def notify(target: String, text: String): F[Unit]
}
import cats.Monad
def income[F[_]](implicit M: Monad[F], C: Capabilities[F]): F[Unit] =
for {
contents <- C.resource("sales.csv")
total = contents
.split("\n").toList.tail // Collection of lines, drop the CSV header
.map { _.split(",").toList match // List[Double] - prices of each of the entries
{ case name :: price :: Nil => price.toDouble }
}
.sum
_ <- C.notify("admin@shop.com", s"Total income made today: $total")
} yield ()
为了编译,我必须包括:
import cats.implicits._
没有这个,我得到一个错误:
Error:(21, 27) value map is not a member of type parameter F[String]
contents <- C.resource("sales.csv")
两个问题:
F
的类型事先未知。但是有Monad
和Capabilities
为F
定义了implicitly
。为什么 Scala 编译器不能在没有从猫中隐式导入的情况下识别它。
- 通常我更喜欢找到某种类型,而不是从
cats
中导入所有东西。例如,更准确地说,仅导入 cats.instances.list._
。 cats.implicits._
中的 Scala 编译器究竟使用了什么来编译这段代码?更重要的是,您使用什么算法来找到它?
- 我还发现,如果我添加
-Xprint-args
选项,即使没有 cats.implicits._
导入,代码也能成功编译。你能解释一下,它是如何影响它的吗?
如果没有隐式导入,Scala 编译器无法识别的只是语法。无需导入即可正确解析实例(由于隐式参数)。
在 cats.implicits._
中你实际上只使用了
import cats.syntax.functor._
import cats.syntax.flatMap._
https://github.com/scala/scala/pull/5909
The option behaves like -Xshow-phases
and stops the compiler after printing.
无需导入语法即可编写
def income[F[_]](implicit M: Monad[F], C: Capabilities[F]): F[Unit] =
M.flatMap(C.resource("sales.csv"))(contents => {
val total = contents
.split("\n").toList.tail // Collection of lines, drop the CSV header
.map {
_.split(",").toList match // List[Double] - prices of each of the entries
{ case name :: price :: Nil => price.toDouble }
}
.sum
M.map(C.notify("admin@shop.com", s"Total income made today: $total"))(_ => ())
})
例子取自Tagless Final in Mastering Functional Programming:
trait Capabilities[F[_]] {
def resource(name: String): F[String]
def notify(target: String, text: String): F[Unit]
}
import cats.Monad
def income[F[_]](implicit M: Monad[F], C: Capabilities[F]): F[Unit] =
for {
contents <- C.resource("sales.csv")
total = contents
.split("\n").toList.tail // Collection of lines, drop the CSV header
.map { _.split(",").toList match // List[Double] - prices of each of the entries
{ case name :: price :: Nil => price.toDouble }
}
.sum
_ <- C.notify("admin@shop.com", s"Total income made today: $total")
} yield ()
为了编译,我必须包括:
import cats.implicits._
没有这个,我得到一个错误:
Error:(21, 27) value map is not a member of type parameter F[String] contents <- C.resource("sales.csv")
两个问题:
F
的类型事先未知。但是有Monad
和Capabilities
为F
定义了implicitly
。为什么 Scala 编译器不能在没有从猫中隐式导入的情况下识别它。- 通常我更喜欢找到某种类型,而不是从
cats
中导入所有东西。例如,更准确地说,仅导入cats.instances.list._
。cats.implicits._
中的 Scala 编译器究竟使用了什么来编译这段代码?更重要的是,您使用什么算法来找到它? - 我还发现,如果我添加
-Xprint-args
选项,即使没有cats.implicits._
导入,代码也能成功编译。你能解释一下,它是如何影响它的吗?
如果没有隐式导入,Scala 编译器无法识别的只是语法。无需导入即可正确解析实例(由于隐式参数)。
在
cats.implicits._
中你实际上只使用了import cats.syntax.functor._ import cats.syntax.flatMap._
https://github.com/scala/scala/pull/5909
The option behaves like
-Xshow-phases
and stops the compiler after printing.
无需导入语法即可编写
def income[F[_]](implicit M: Monad[F], C: Capabilities[F]): F[Unit] =
M.flatMap(C.resource("sales.csv"))(contents => {
val total = contents
.split("\n").toList.tail // Collection of lines, drop the CSV header
.map {
_.split(",").toList match // List[Double] - prices of each of the entries
{ case name :: price :: Nil => price.toDouble }
}
.sum
M.map(C.notify("admin@shop.com", s"Total income made today: $total"))(_ => ())
})