【问题标题】:Monads - Purpose of FlattenMonads - 扁平化的目的
【发布时间】:2021-05-05 07:22:17
【问题描述】:

所以我一直在阅读有关 Scala 中的 Monads 以及与它们的 flatMap 函数和 for 理解相关的所有语法。直观地说,我理解为什么 Monads 需要使用 flatMap 函数的 map 部分,就像我通常在使用 map 函数时一样,它在一个包含零个、一个或多个元素的容器上并返回相同的容器,但带有传入的函数应用于容器的所有元素。 Monad 同样是一个包含零个、一个或多个元素的容器。

但是,flatMapflatten 部分的用途是什么?我无法理解它背后的直觉。对我来说,这似乎是额外的样板文件,需要传递给flatMap 的所有函数围绕它们的返回值创建一个容器/monad,只是为了让该容器立即被flatMapflatten 部分销毁。我想不出一个使用flatMap 的示例,它不能通过简单地替换为map 来简化。例如:

var monad = Option(5)
var monad2 = None

def flatAdder(i:Int) = Option(i + 1)
def adder(i:Int) = i + 1

// What I see in all the examples
monad.flatMap(flatAdder)
// Option[Int] = Some(6)
monad.flatMap(flatAdder).flatMap(flatAdder)
// Option[Int] = Some(7)
monad2.flatMap(flatAdder)
// Option[Int] = None
monad2.flatMap(flatAdder).flatMap(flatAdder)
// Option[Int] = None

// Isn't this a lot easier?
monad.map(adder)
// Option[Int] = Some(6)
monad.map(adder).map(adder)
// Option[Int] = Some(7)
monad2.map(adder)
// Option[Int] = None
monad2.map(adder).map(adder)
// Option[Int] = None

对我来说,单独使用map 似乎比flatMap 更直观和简单,而flatten 部分似乎没有增加任何价值。然而,在 Scala 中,重点放在flatMap 而不是map,以至于它甚至有自己的for 解析语法,所以很明显我一定遗漏了一些东西。我的问题是:在什么情况下,flatMapflatten 部分实际上有用?以及flatMapmap 有哪些其他优势?

【问题讨论】:

  • 如果那是您经常看到的示例,恕我直言,示例 (可能是教程) 很糟糕,因为正如您所说,没有任何意义创建一个容器来将其展平。 - flatMap 的更好示例是使用 List 替换嵌套循环,使用 Option 组合无法返回值的多个函数,使用 Either 组合验证b>,使用 Future 组合异步调用。 - 无论如何是的,如果您不需要创建内部 "container" 则不要这样做,但现实是大多数时候A => F[B] 函数很常见

标签: scala monads flatmap


【解决方案1】:

如果正在处理的每个元素都可能导致零个或多个元素怎么办?

List(4, 0, 15).flatMap(n => primeFactors(n))
//List(2, 2, 3, 5)

如果您有一个可能拼写不正确的名字,并且您想要他们的办公室任务(如果他们有的话)怎么办?

def getID(name:String): Option[EmployeeID] = ???
def getOffice(id:EmployeeID): Option[Office] = ???

val office :Option[Office] =
  getID(nameAttempt).flatMap(id => getOffice(id))

当您拥有一个 monad 并且需要将其内容提供给 monad 生产者时,您使用 flatMap()。你想要的结果是Monad[X] 而不是Monad[Monad[X]]

【讨论】:

    【解决方案2】:

    flatMap 背后的想法是能够获取 M[A] 的值和具有 A => M[B] 类型的函数 f 并生成 M[B],如果我们没有办法"flatten" 的值,那么我们总是会得到一个 M[M[B]],这是我们大多数时候不想要的。 (是的,在某些情况下,您可能需要 M[M[_]],例如当您想创建多个 M[_] 实例时)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 2017-03-19
      • 2015-09-15
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多