- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我似乎真的不太理解Map和FlatMap。我无法理解的是 for 理解如何是对 map 和 flatMap 的一系列嵌套调用。以下示例来自Functional Programming in Scala
def bothMatch(pat:String,pat2:String,s:String):Option[Boolean] = for {
f <- mkMatcher(pat)
g <- mkMatcher(pat2)
} yield f(s) && g(s)
翻译为
def bothMatch(pat:String,pat2:String,s:String):Option[Boolean] =
mkMatcher(pat) flatMap (f =>
mkMatcher(pat2) map (g => f(s) && g(s)))
mkMatcher方法定义如下:
def mkMatcher(pat:String):Option[String => Boolean] =
pattern(pat) map (p => (s:String) => p.matcher(s).matches)
模式方法如下:
import java.util.regex._
def pattern(s:String):Option[Pattern] =
try {
Some(Pattern.compile(s))
}catch{
case e: PatternSyntaxException => None
}
如果有人能在这里阐明使用 map 和 flatMap 背后的基本原理,那就太好了。
最佳答案
TL;DR 直接进入最终示例
我会尝试重述一下。
定义
for
理解是组合 flatMap
的语法快捷方式和map
以易于阅读和推理的方式。
让我们稍微简化一下,假设每个 class
提供上述两种方法的可以称为 monad
我们将使用符号M[A]
表示 monad
具有内部类型A
.
示例
一些常见的单子(monad)包括:
List[String]
在哪里
M[X] = List[X]
A = String
Option[Int]
在哪里
M[X] = Option[X]
A = Int
Future[String => Boolean]
在哪里
M[X] = Future[X]
A = (String => Boolean)
map 和平面 map
在通用 monad 中定义 M[A]
/* applies a transformation of the monad "content" mantaining the
* monad "external shape"
* i.e. a List remains a List and an Option remains an Option
* but the inner type changes
*/
def map(f: A => B): M[B]
/* applies a transformation of the monad "content" by composing
* this monad with an operation resulting in another monad instance
* of the same type
*/
def flatMap(f: A => M[B]): M[B]
例如
val list = List("neo", "smith", "trinity")
//converts each character of the string to its corresponding code
val f: String => List[Int] = s => s.map(_.toInt).toList
list map f
>> List(List(110, 101, 111), List(115, 109, 105, 116, 104), List(116, 114, 105, 110, 105, 116, 121))
list flatMap f
>> List(110, 101, 111, 115, 109, 105, 116, 104, 116, 114, 105, 110, 105, 116, 121)
用于表达
表达式中的每一行都使用 <-
符号被转换为 flatMap
调用,最后一行除外,该行被翻译为结论 map
调用,其中左侧的“绑定(bind)符号”作为参数传递给参数函数(我们之前称为 f: A => M[B]
):
// The following ...
for {
bound <- list
out <- f(bound)
} yield out
// ... is translated by the Scala compiler as ...
list.flatMap { bound =>
f(bound).map { out =>
out
}
}
// ... which can be simplified as ...
list.flatMap { bound =>
f(bound)
}
// ... which is just another way of writing:
list flatMap f
只有一个 <-
的 for 表达式转换为map
使用作为参数传递的表达式进行调用:
// The following ...
for {
bound <- list
} yield f(bound)
// ... is translated by the Scala compiler as ...
list.map { bound =>
f(bound)
}
// ... which is just another way of writing:
list map f
现在进入正题
如您所见,map
操作保留了原始的“形状”monad
,所以 yield
也会发生同样的情况表达式:a List
仍然是List
yield
中的操作转换后的内容.
另一方面,for
中的每个绑定(bind)行只是连续的 monads
的组合,必须“压平”以保持单一的“外部形状”。
假设每个内部绑定(bind)都被转换为 map
打电话,但右手是一样的 A => M[B]
函数,你最终会得到 M[M[B]]
对于理解中的每一行。
整体意图for
语法的目的是轻松地“展平”连续的一元操作的串联(即以“一元形状”“提升”值的操作: A => M[B]
),并添加最后的 map
。 可能执行最终转换的操作。
我希望这能解释翻译选择背后的逻辑,它以机械的方式应用,即:n
flatMap
由单个 map
结束的嵌套调用打电话。
一个人为的说明性示例
旨在展示 for
的表现力语法
case class Customer(value: Int)
case class Consultant(portfolio: List[Customer])
case class Branch(consultants: List[Consultant])
case class Company(branches: List[Branch])
def getCompanyValue(company: Company): Int = {
val valuesList = for {
branch <- company.branches
consultant <- branch.consultants
customer <- consultant.portfolio
} yield (customer.value)
valuesList reduce (_ + _)
}
你能猜出valuesList
的类型吗?
如前所述,monad
的形状通过理解来维持,所以我们从 List
开始在company.branches
,并且必须以 List
结尾.
相反,内部类型会发生变化,并由 yield
确定。表达式:即customer.value: Int
valueList
应该是List[Int]
关于scala - 与 FlatMap/Map 转换的 for 理解相混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14598990/
我有一个对象Foo,其中包含Bar列表。这些类的描述如下: class Foo { String name; List bars = new ArrayList(); Foo(
根据 Mozilla 开发者网站: flatMap() 方法首先使用映射函数映射每个元素,然后将结果展平到一个新数组中。它与 map 后跟深度为 1 的 flat 相同,但 flatMap 通常非常有
我对无法找到该问题的现有问题感到非常惊讶。这是为什么,鉴于: val p: Int => Option[Int] = Some(_) List(1, 2, 3).flatMap(p) 我得到: :14
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 5 年前。 Improve th
我想知道两种平面映射情况之间是否存在显着差异。 案例 1: someCollection .stream() .map(CollectionElement::getAnotherCol
以下是flatMap的定义取自 scala.util.Success。 final case class Success[+T](value: T) extends Try[T] { def fl
我正在寻找一个函数来展平列表数组。首先,我在 RDD 系统上使用 Apach Spark 函数 flatMap 实现了我的解决方案,但我想在本地执行此操作。但是,我无法找到 的等价物 samples
我想知道是否存在忽略 flatMap 中的结果的函数(在 scala 或 cat 中) .例如。 Some("ignore this").ignoreArgumentFlatMap(Some("res
我正在学习 Scala 并解决了 99 个 Scala 问题。对于以下练习: 展平嵌套列表结构。示例: scala> flatten(List(List(1, 1), 2, List(3, List(
当编译器进入无限循环时,是否有人遇到过使用此类 flatMap 链(或什至更长)的问题。 let what = Future.init { (promise) in promise(.succ
有没有更好的函数方式来写 flatMap ? def flatMap[A,B](list: List[A])(f: A => List[B]): List[B] = list.map(x =>
我试图从两个 中变出笛卡尔积潜在无限然后我通过 limit() 限制的流. 到目前为止,这(大约)是我的策略: @Test void flatMapIsLazy() { Stream.
为什么以下声明对 .map() 有效但不适用于 .flatMap() ? val tupled = input.map(x => (x*2, x*3)) //Compilation error:
我正在寻找可以同时映射和展平 Lists 和 Maybes 的代码。我在 this topic 中发现了这样一个 flatMap 函数: flatMap :: (t -> [a]) -> [t] ->
考虑在某些大小写匹配上编写的 flatMap。例如: list.flatMap( v => v match { case Cond1 => if(something) Some
我无法使用ListKOf平面映射T -> Option。 例如 listOf(1,2,3).k().flatMap { i -> if (i % 2 == 0) Some(i) else None
有人可以解释我如何在RxJava中通过flatMap运算符传递onComplete信号吗? 如果对flatMap运算符进行注释,则可以获取1到10的数字列表,这意味着toList将收到onComple
我正在做一个在线类(class)并误读了一个问题(这就是为什么我认为可以发布这个问题,因为答案与类(class)中的问题无关!)。 data class Trip( val drive
给定作为数据类的二维坐标列表 data class Point(val x: Int, val y:Int) val points: List 和 TornadoFX(Kotlin 中的 JavaFX
这个问题已经有答案了: What is the difference between .stream() and Stream.of? (5 个回答) 已关闭 3 年前。 我有以下代码: List p
我是一名优秀的程序员,十分优秀!