【问题标题】:Combine monads into tuples operator scalaz将 monad 组合成元组 operator scalaz
【发布时间】:2015-03-12 16:43:09
【问题描述】:

因此,Scala 中一个非常常见的模式是 for 理解,如下所示:

for {
  i <- monadA
  j <- monadB
} yield (i, j)

对于 3 元组、...、n 元组也是如此。这在我的代码中变得如此普遍,我想 scalaz 提供了一些很棒的运算符来为我做这件事,例如monadA funnyOperator monadB funnyOperator monadC。我环顾四周,似乎找不到任何东西。因此,我为 2 元组和 3 元组定义了自己的隐式类,但更喜欢使用 scalaz。

奖金

作为对当前接受的答案的回应,希望有人告诉如何编译:

import scalaz.Scalaz._

// Like a 1 element list
case class MyMonad[+T](x: T) {
  def map[U](f: T => U): MyMonad[U] = MyMonad(f(x))
  def flatMap[U](f: T => MyMonad[U]): MyMonad[U] = f(x)
}

val myMonad: MyMonad[(Int, Int)] = (MyMonad(1) |@| MyMonad(2)).tupled

不给:

error: value |@| is not a member of MyMonad[Int]

奖励解决方案:

您需要“提供一个应用实例”,例如

implicit def myMonadApplicative: Bind[MyMonad] = new Bind[MyMonad] {
  def bind[A, B](fa: MyMonad[A])(f: A => MyMonad[B]): MyMonad[B] = fa.flatMap(f)
  def map[A, B](fa: MyMonad[A])(f: A => B): MyMonad[B] = fa.map(f)
}

【问题讨论】:

  • 这不是重复的,我是专门寻找与所有 Monad 相关的语法糖。链接的问题询问如何基本上对 Options 进行理解。
  • 答案仍然适用。尽管有问题,但Option 并没有什么特别之处。
  • 好吧,我为|@| 做了一个CMD + F,但它不存在,也没有我要求的任何其他类型的运算符。
  • 存在另一个答案的事实并不意味着问题不一样

标签: scala functional-programming monads scalaz


【解决方案1】:

你可以使用sequence;我永远不记得你是否需要 shapeless-scalaz:

(monadA, monadB).sequence
(monadA, monadB, monadC).sequence

【讨论】:

【解决方案2】:

鉴于每个Monad 都是Applicative,您也可以使用

(monadA |@| monadB).tupled

例如

scala> val b: List[(Int, Int)] = (List(1, 2, 3) |@| List(4, 6)).tupled
b: List[(Int, Int)] = List((1,4), (1,6), (2,4), (2,6), (3,4), (3,6))

【讨论】:

  • 谢谢!我编辑使用tupled,因为它有点整洁,并且如果单子的数量发生变化也不会改变语法。不过,它似乎不适用于具有flatMapmap所有类型。我使用自定义 Monad 进行了尝试,但出现编译器错误。我需要让它发挥作用吗? (更新问题)
  • @samthebest |@|是应用生成器运算符。您需要为您的自定义类提供一个 Applicative 实例,以使其正常工作。
猜你喜欢
  • 1970-01-01
  • 2015-12-07
  • 2020-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-16
相关资源
最近更新 更多