【问题标题】:Conversion between Option[F[ShoppingCart]] to F[Option[ShoppingCart]]Option[F[ShoppingCart]] 到 F[Option[ShoppingCart]] 之间的转换
【发布时间】:2021-06-05 14:34:48
【问题描述】:

我在 Scala 中有以下代数(我使用的是无标记最终模式):

trait ShoppingCarts[F[_]] {
  def create(id: String): F[Unit]
  def find(id: String): F[Option[ShoppingCart]]
  def add(sc: ShoppingCart, product: Product): F[ShoppingCart]
}

使用上面的代数,我创建了以下程序:

def createAndToCart[F[_] : Monad : ShoppingCarts](product: Product, cartId: String): F[Option[ShoppingCart]] =
  for {
    _ <- ShoppingCarts[F].create(cartId)
    maybeSc <- ShoppingCarts[F].find(cartId)
    maybeNewScF = maybeSc.map(sc => ShoppingCarts[F].add(sc, product))
    maybeNewSc <- maybeNewScF match {
      case Some(d) => d.map(s1 => Option.apply(s1))
      case _ => Monad[F].pure(Option.empty[ShoppingCart])
    }
  } yield maybeNewSc

我不太喜欢 for-comprehension 构造中将Option[F[ShoppingCart]] 转换为F[Option[ShoppingCart]] 的代码。我确信我可以做得更好,但我不知道如何改进它。

我正在使用猫。

【问题讨论】:

    标签: scala functional-programming scala-cats cats-effect tagless-final


    【解决方案1】:

    您正在寻找traversesequence。这些函数所做的是“切换”效果的顺序,因此如果 G 有一个 Applicative 的实例,它们就能够将 G[F[A]] 更改为 F[G[A]]Option 在范围内有这样一个实例,所以你可以使用它。

    traverse 带有额外的映射功能,但如果你只是想“切换”效果,那么sequence 将是一种方式:

    for {
          _ <- ShoppingCarts[F].create(cartId)
          maybeSc <- ShoppingCarts[F].find(cartId)
          maybeNewSc <- maybeSc.map(sc => ShoppingCarts[F].add(sc, product)).sequence //here you need to use sequence
    } yield maybeNewSc
    

    或者您可以将mapsequencetraverse 合并为一个步骤:

    for {
          _ <- ShoppingCarts[F].create(cartId)
          maybeSc <- ShoppingCarts[F].find(cartId)
          maybeNewSc <- maybeSc.traverse(sc => ShoppingCarts[F].add(sc, product))
    } yield maybeNewSc
    

    您可以在cats docs 中阅读有关sequencetraverse 的更多信息。

    我建议您检查的另一件事是 monad transformers,因为它们使处理像 F[Option[A]] 这样的嵌套 monad 堆栈变得容易得多。

    【讨论】:

    • 拜托,您能从 Cats 库中添加所需的导入吗?
    • 如果你使用的是比较新版本的猫,你可以使用import cats.syntax.all._
    猜你喜欢
    • 2019-12-27
    • 2017-01-13
    • 1970-01-01
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    相关资源
    最近更新 更多