scala - How to go from a List[F[String]] to F[List[String]] using Scala and Cats?
问题描述
I'm new to Cats and I don't know how to overcome this situation. In the code bellow:
class Example[F[_]] {
import cats._
import cats.data._
import cats.syntax.all._
def saveAll(list: List[String])(implicit M: Monad[F]): F[List[String]] = {
val result: List[F[String]] =
list.map(saveOne)
}
def saveOne(s: String)(implicit M: Monad[F]): F[String] = s"Saved $s".pure[F]
}
How do I transform the result
variable, in the saveAll
function, to make sure it matches its expected return type?
Thanks.
解决方案
这种转换是通过以下traverse
操作完成的:
class Example[F[_]] {
import cats._
import cats.implicits._
def saveAll(list: List[String])(implicit M: Monad[F]): F[List[String]] =
list.traverse(saveOne)
def saveOne(s: String)(implicit M: Monad[F]): F[String] =
s"Saved $s".pure[F]
}
traverse
从 typeclass中的方法签名可以看出,Traverse
它需要一个 的实例Applicative
,而不是一个Monad
:
trait Traverse[F[_]] {
def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]]
}
在猫中,每种类型都有 aMonad
也有一个Applicative
,因此Example
该类甚至可以使用Monad
.
但反过来是不正确的。有些类型只有一个Applicative
实例。其中最值得注意的是Validated
。您可以在cat 文档中阅读有关实现Monad
for问题的更多信息。Validated
因此,如果您请求一个实例,则此代码将更通用Applicative
:
class Example[F[_]] {
import cats._
import cats.implicits._
def saveAll(list: List[String])(implicit M: Applicative[F]): F[List[String]] =
list.traverse(saveOne)
def saveOne(s: String)(implicit M: Applicative[F]): F[String] =
s"Saved $s".pure[F]
}
推荐阅读
- android - 将 ConstraintLayout 更新到 1.1.0 后的 Android UI 问题
- vba - 创建 VBA 以更改多个数据透视表中的数据源时出错
- oracle - sql developer导出数据库-没有要导出的对象
- angular - 允许 nginx 服务器中的静态内容的 POST 请求
- python - 在 python 中使用 bash 命令脚本
- javascript - 在 JSContext 中暂停/停止评估脚本
- python - Keras fit_generator:生成器内的随机增强+洗牌
- tfs - 如何将工作方式设置为 Lock-Modify-Unlock tfs?
- crystal-reports - 无法在 vs2017 中加载文件或程序集“log4net”、“crystaldecisions.reportappserver.clientdoc”
- google-apps-script - 当特定值为 0 时发送电子邮件