大多数教科书都将flatMap
描述为flatten
和map
的组合。虽然理解map
并不是那么难,但对于flatten
的语义来说,事情变得不那么清楚了(对我来说)。特别是,我不明白为什么可以展平List(选项(3)),而在选项(List(3))上也不可能这样做。有人可以澄清吗?
scala> List(Option(3)).flatten
res9: List[Int] = List(3)
scala> Option(List(3)).flatten
<console>:12: error: Cannot prove that List[Int] <:< Option[B].
Option(List(3)).flatten
^
答案 0 :(得分:1)
<:<
中的List[Int] <:< Option[B]
表示“是近似的子类型。” flatten
要求内部的类型可以转换为外部类型。对于Lists
和Options
,此转化只能采用一种方式。 Option(3)
可以转换为List(3)
,但List(1,2,3,4)
无法转换为Option(1,2,3,4)
,因为Options
最多可以包含一个项目。
答案 1 :(得分:0)
如果你在第二个选项的List中有多个项目会怎么样?...没有从Iterable(例如List)到Option的隐式转换,因为在编译期间没有办法确保Iterable有一个或多个cero项目,它可能有更多,所以,不可能转换为选项。这就是它背后的哲学。
它背后的机制是@RestController
@RequestMapping("/v1")
class MainController(@Autowired private val teamsService: TeamsService) {
@GetMapping("/teams")
fun teams(): String? = teamsService.findAll()
}
s,类implicit
(是的,它是一个类,名称为<:<[A,B]
,可以加注到<:<
),以及从Option到Iterable的隐式方法。
因此方法A <:< B
的意思是它需要隐式类型(在您的情况下)flatten
或<:<[List[Int],Option[Int]]
。
该类只有一个定义,它仅适用于<:<[Option[Int],List[Int]]
。这样编译只能在你使用同一个类时找到证据,而不是这种情况。但是如果之前,Option被转换为Traversable,那么编译器就可以找到证据
<:<[A,A]
... <:<[Traversable[Int],Traversable[Int]]
存在此隐式转换,而Option
已经是Traversable。
在这种情况下,存在从List
到Option[A]
的隐式转换,因此编译器使用它并找到类Traversable[A]
...希望它很清楚!
以防万一,请检查this line of Scala's sourcecode。