我在Scala 2.10中遇到了用于理解的语法问题。在Scala中用于理解的补救语法问题
for(a <- List(Some(1,2)); b <- a) yield b
评估为List(1,2)
那么为什么不for(a <- Some(List(1,2)); b <- a) yield b
评价同一件事?
的类型检查抱怨说,它发现了一个List[Int]
期待的Option[?]
我在Scala 2.10中遇到了用于理解的语法问题。在Scala中用于理解的补救语法问题
for(a <- List(Some(1,2)); b <- a) yield b
评估为List(1,2)
那么为什么不for(a <- Some(List(1,2)); b <- a) yield b
评价同一件事?
的类型检查抱怨说,它发现了一个List[Int]
期待的Option[?]
当我说明了这是最近第二个表达式(b <-a
) - 希望有人能找到的链接。这是一个反复出现的问题,所以它可能会被关闭。
无论如何,外部生成器控制着表示。这发生在每一个级别,所以如果我有这样的:
for {
a <- A
b <- B
c <- C
} yield f(a, b, c)
随后的f(a, b, c)
表示由C
控制,那表示由B
控制,最终结果的表述由A
控制。因此,对于大多数实际用途,理解的表示由第一个生成器控制。
那么“代表性”是什么意思?那么,理解是一个单子理解,通常(实际上,这只是一组调用方法,如flatMap
和map
,所以它可以是任何 typechecks)。这意味着给定一个单子M[A]
和一个函数A => M[B]
,那么你可以在M[B]
中变换M[A]
,其中单子的M
是“表示”。
这意味着,在大多数情况下,将Option
和List
组合在一起用于理解是不可能的。所有的藏品在GenTraversableOnce
中都有一个共同的父项,所以在组合它们时没有任何问题(尽管事情比底层的要复杂得多)。
但是,存在从Option
到Iterable
的隐式转换。既然如此,当斯卡拉在第一个例子中发现b <- a
,并且知道它不能通过Option
,因为理解由List
“控制”,它将Option
转换为Iterable
,并且一切正常。
但是,在第二种情况下不会发生这种情况。做一个Option
的理解是好的,所以没有必要将它转换成Iterable
。遗憾的是,不能将List
转换为Option
(这种转换的结果是什么?),这会导致错误。
Scala不会“回溯”到a <- Some(List(1, 2))
并对其应用隐式转换,因为Scala中的类型推断只能继续前进 - 它之前决定的内容将保持不变。
我衷心推荐你看看相关的问题,并理解翻译理解的方式。
谢谢丹尼尔。如果问题是重复的,我不会感到惊讶,因为它很难搜索,关于理解的“斯卡拉之旅”doc不能解释这种行为。真正绊倒我的是(a < - Some(List(1,2)); b <-a){println(b)}的行为与我预期的相同,即'b'评估为潜在的Ints。 – 2013-02-19 15:53:58
@DanielSchobel那么,如果没有“收益率”,你没有返回任何东西,所以没有问题。既然你不能有'一些(1,2)',你不能有'yield'版本。 – 2013-02-19 23:22:49
丹尼尔解释了这个错综复杂。但是我想补充一些细节,因为就你而言,我发现这种行为令人难以置信地不直观,而且我遇到了几次混合Option
和List
的问题。这是特别烦人的,因为如你所见,它在一个方向而不是另一个方向工作。
所以根据换理解规则,你将有
def test(a: Option[List[Int]]) = a.flatMap(_.map(identity))
与
<console>:7: error: type mismatch;
found : List[Int]
required: Option[?]
def test(a: Option[List[Int]]) = a.flatMap(_.map(identity))
^
失败,但你可以把它的工作:
def test(a: Option[List[Int]]) = (a: Iterable[List[Int]]).flatMap(_.map(identity))
test(Some(List(1,2))) // List(1,2)
或背部有for
:
for(a <- Some(List(1,2)).toIterable; b <- a) yield b
for
应该自己强加这个转换吗?我不太清楚,但我分享你的惊喜,它不起作用。
Upvoted for the work-around,我同意,它似乎应该以原始形式工作,特别是在我对Daniel的评论中指出,对于(a < - Some(List(1,2)); b < - a){println(b)}的工作原理与您所期望的完全相同,即b对底层的Ints进行了处理。 – 2013-02-19 16:01:47
可能的重复[类型不匹配Scala理解](http://stackoverflow.com/questions/4719592/type-mismatch-on-scala-for-comprehension) – 2013-02-19 07:06:49
它也是重复的[困惑与for-理解到flatMap/map转换](http://stackoverflow.com/questions/14598990/confused-with-the-for-comprehension-to-flatmap-map-transformation) – 2013-02-19 08:55:48