首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala中与for-comprehension有关的补救性语法问题

Scala中与for-comprehension有关的补救性语法问题
EN

Stack Overflow用户
提问于 2013-02-19 12:25:59
回答 2查看 299关注 0票数 2

在Scala 2.10中,我遇到了for-comprehension的语法问题。

for(a <- List(Some(1,2)); b <- a) yield b的计算结果为List(1,2)

那么,为什么for(a <- Some(List(1,2)); b <- a) yield b的计算结果不是相同的呢?

类型检查器抱怨第二个表达式(b <-a),说它在期望List[Int]时发现了Option[?]

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-19 12:56:56

我最近已经解释过这一点--希望有人能找到其中的联系。这是一个反复出现的问题,所以它很可能会被关闭。

无论如何,外部生成器控制表示。这在每一层都会发生,所以如果我有这个:

代码语言:javascript
复制
for { 
  a <- A
  b <- B
  c <- C
} yield f(a, b, c)

然后,f(a, b, c)的表示由C控制,B的表示由B控制,最终结果的表示由A控制。因此,对于大多数实际目的,for purposes的表示是由第一个生成器控制的。

那么,我所说的“代表性”是什么意思?for monadic通常是一元理解(实际上,它只是对flatMapmap等方法的一组调用,所以它可以是任何类型检查的内容)。这意味着给定一个单数M[A]和一个函数A => M[B],然后您可以在M[B]中转换M[A],其中单数M是“表示”。

这意味着,在大多数情况下,不可能将OptionList组合在一起以进行理解。所有的集合在GenTraversableOnce中都有一个共同的父类,所以组合它们没有问题(尽管事情比幕后复杂得多)。

但是,存在从OptionIterable的隐式转换。在这种情况下,当Scala在第一个示例中找到b <- a,并且知道它不能传递Option,因为理解是由List“控制”的,它将Option转换为Iterable,然后一切正常。

然而,在第二种情况下不会发生这种情况。用Option做一个for理解是可以的,所以不需要把它转换成一个Iterable。不幸的是,无法将List转换为Option (这种转换的结果会是什么?),这会导致错误。

Scala不会“回溯”到a <- Some(List(1, 2))并对其应用隐式转换,因为Scala中的类型推断只会向前推进--它之前所做的决定将保持不变。

我强烈建议您查看相关的问题,并了解如何翻译for comprehension。

票数 7
EN

Stack Overflow用户

发布于 2013-02-19 16:59:01

丹尼尔解释了其中的复杂之处。但我想补充一些细节,因为和你一样,我发现这种行为非常不直观,我自己也遇到过几次将OptionList混合在一起的问题。它特别烦人,因为正如您所看到的,它只在一个方向上工作,而不是在另一个方向上工作。

所以根据理解规则,你将会有

代码语言:javascript
复制
def test(a: Option[List[Int]]) = a.flatMap(_.map(identity))

失败的原因是

代码语言:javascript
复制
<console>:7: error: type mismatch;
 found   : List[Int]
 required: Option[?]
           def test(a: Option[List[Int]]) = a.flatMap(_.map(identity))
                                                           ^

但是你可以让它工作:

代码语言:javascript
复制
def test(a: Option[List[Int]]) = (a: Iterable[List[Int]]).flatMap(_.map(identity))

test(Some(List(1,2)))  // List(1,2)

或者回到for

代码语言:javascript
复制
for(a <- Some(List(1,2)).toIterable; b <- a) yield b

for是否应该自己强制执行此转换?老实说,我不知道,但我和你一样惊讶于它不起作用。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14949831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档