理解flatten的语义

时间:2018-04-10 11:44:57

标签: functional-programming flatten

大多数教科书都将flatMap描述为flattenmap的组合。虽然理解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
                       ^

2 个答案:

答案 0 :(得分:1)

<:<中的List[Int] <:< Option[B]表示“是近似的子类型。” flatten要求内部的类型可以转换为外部类型。对于ListsOptions,此转化只能采用一种方式。 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。 在这种情况下,存在从ListOption[A]的隐式转换,因此编译器使用它并找到类Traversable[A] ...希望它很清楚!

以防万一,请检查this line of Scala's sourcecode