好的,我决定尝试一下,并且我想撤回我的评论:
也许您可以定义一个隐式类,该类具有作用于 Product 上的“log”方法?
我曾自信地认为 Future 和所有单子(集合、选项)都有共同的祖先,结果我错了。我有以下解决方案,而不使用 Cats。这在 cats 中可以以更漂亮的方式完成,除了前面提到的 "flatTap",还可以使用可能的 cats.Ref 等进行装饰。
未来在这里显然是个例外,但是随着更多的异常出现,您可能需要扩展此对象。
import scala.concurrent._
import ExecutionContext.Implicits.global
object MonadicConv {
implicit class MonadicLog[+B <: Product, A] (val u: B){
def log(l: String, args: List[A] = List()): B = {
println("logging")
println(u)
println(l)
u
}
}
implicit class FutureLog[T, A](val u: Future[T]){
def log(l: String, args: List[A] = List()) : Future[T] = {
println("logging")
println(u)
println(l)
u
}
}
}
1) 您需要使用自己的日志记录逻辑来修改此内容,我只是在打印。
2) 我对此并不感到非常自豪,因为它不再是一个纯函数。我不确定在Scala中是否有一种方法可以解决这个问题而不使用Cats。(可能有)
3) args可以被删除,只是添加了它们,以防您想要传递额外的信息。
4) 如果您真的想将它们合并,可以尝试定义自己的product,一些线索:在Scala中实现具有通用更新函数的产品类型,该函数适用于其部分
您可以使用此功能。
import MonadicConv._
val x = Some(5).log("").get
val lx = List(Some(5), Some(10), Some(1)).log("list").flatten.log("x").filter(_ > 1).log("")
val ff = Future.successful(List(Some(5), Some(10), Some(1))).log("fff").map(_.flatten.filter(_ > 1).log("inner")).log("")
这将打印出:
这将打印出
logging
Some(5)
option test
logging
List(Some(5), Some(10), Some(1))
list test
logging
List(5, 10, 1)
flat test
logging
List(5, 10)
filter test
logging
Future(Success(List(Some(5), Some(10), Some(1))))
future test
logging
Future(<not completed>)
incomplete test
logging
List(5, 10)
inner future test
在这里,我提到过,目前这真的是Cats领域。这是我在核心Scala中能想到的最好的解决方案。
Scastie版本在这里
flatTap
不适合像OP在最后一个示例中展示的那样进行链接。 - smac89tapEach()
,但它在Future
上不可用。我想知道为什么。也许在下一个版本中会有吧? - jwvhtapEach()
。它只在Iterable
中实现。在Option
中使用它会返回一个List
。 - pme