首页 > 解决方案 > Monads - 扁平化的目的

问题描述

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

但是,该flatten部分的目的是flatMap什么?我无法理解它背后的直觉。对我来说,这似乎是额外的样板文件,需要传递给的所有函数flatMap围绕它们的返回值创建一个容器/monad,只是为了让该容器立即flattenflatMap. 我想不出一个简单的例子,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理解语法,所以很明显我一定遗漏了一些东西。我的问题是:在什么情况下,这flatten部分flatMap实际上有用?还有什么其他优势flatMapmap

标签: scalamonadsflatmap

解决方案


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

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))

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


推荐阅读