使用 Scala Cats 将函数列表应用于值

Apply list of functions to value using Scala Cats

在 haskell 我可以对字符串执行以下操作

let f = sequence [id, reverse]
f "test" 

我有点不知道如何使用 Cats 以更好的方法来解决这个问题。我目前有类似

val f = List(fun1,fun2)
val data = "test"

f map {fun => fun(data)} 

是否有可以使用 Cats 完成此操作的 Sequence 或 SequenceU 实现?

它或多或少完全一样,只是语法有点不同,你需要一些额外的导入,而且通用版本不那么方便,因为 Scala 的 String 不仅仅是一个别名对于字符列表:

import cats.instances.function._, cats.instances.list._, cats.syntax.traverse._

val funcs: List[String => String] = List(identity, _.reverse)

val f = funcs.sequenceU

在 Haskell sequence 中,其参数的外部类型构造函数需要一个 Traversable 实例,内部类型构造函数需要一个 Monad 实例。 Cats 的 sequence 几乎一样——Traversable 被称为 Traverse(因为名称 Traversable 已经被标准库采用),并且它需要一个 Applicative实例而不是 Monad(这是一个更准确的约束——Haskell 的 sequence 由于历史原因只需要一个 monad 实例)。

如果您愿意,可以直接导入 cats.implicits._,但这会引入很多其他内容。上面的导入提供了您需要的最小类型 class 实例和语法扩展。

你可以使用 f,这是一个 String => List[String],像这样:

scala> f("test")
res0: List[String] = List(test, tset)

请注意,如果您使用的是 2.12.1 并且启用了 -Ypartial-unification 编译器标志,您可以只写 .sequence,而不是 .sequenceU。为什么在早期的 Scala 版本上需要 U 是一个很长的故事——请参阅我的 blog post here 以获得解释。