Scala中具有理解力的补救语法问题 [英] Remedial syntax issue with for-comprehension in Scala
问题描述
我在Scala 2.10中遇到了语法理解方面的问题.
I'm having syntax issues with a for-comprehension in Scala 2.10.
for(a <- List(Some(1,2)); b <- a) yield b
的计算结果为List(1,2)
那么为什么for(a <- Some(List(1,2)); b <- a) yield b
不能评估相同的东西?
so why doesn't for(a <- Some(List(1,2)); b <- a) yield b
evaluate to the same thing?
类型检查器抱怨第二个表达式(b <-a
)说找到了List[Int]
当期望Option[?]
The type-checker complains about the second expression (b <-a
) saying it found a List[Int]
when expecting an Option[?]
推荐答案
我最近已经对此进行了解释-希望有人可以找到该链接.这是一个反复出现的问题,因此很可能已经解决.
I've explained this very recently -- hopefully someone can find the link. It's a recurring question, so it may well be closed.
无论如何,外部生成器控制表示.这发生在每个级别,所以如果我有这个:
At any rate, the outer generator controls the representation. That happens on each level, so if I have this:
for {
a <- A
b <- B
c <- C
} yield f(a, b, c)
然后,f(a, b, c)
的表示形式由C
控制,其表示形式由B
控制,最终结果的表示形式由A
控制.因此,出于大多数实际目的,用于理解的表示形式是由第一生成器控制的.
Then the representation of f(a, b, c)
is controlled by C
, the representation of that is controlled by B
, and the representation of the final result is controlled by A
. So, for most practical purposes, the representation of the for comprehension is controlled by the first generator.
那么代表"是什么意思?好吧,通常,对于for的理解是单子理解(实际上,它只是对flatMap
和map
之类的方法的一组调用,因此可以进行类型检查的任何 ).这意味着给定一个monad M[A]
和一个函数A => M[B]
,然后您可以在M[B]
中转换M[A]
,其中M
是monad,是表示形式".
So what do I mean by "representation"? Well, a for comprehension is a monadic comprehension, usually (actually, it's just a set of calls to methods like flatMap
and map
, so it can be anything that typechecks). That means that given a monad M[A]
and a function A => M[B]
, then you can transform M[A]
in M[B]
, where M
, the monad, is the "representation".
这意味着,在大多数情况下,将Option
和List
组合在一起以理解是不可能的.所有集合在GenTraversableOnce
中都有一个共同的父代,因此合并它们没有问题(尽管事情比幕后要复杂得多).
This means that, for the most part, it would be impossible to combine Option
and List
in a for comprehension. All the collections have a common parent in GenTraversableOnce
, so there's no problem in combining them (though things are much more complicated than that under the hood).
但是,存在从Option
到Iterable
的隐式转换.就是这种情况,当Scala在第一个示例中找到b <- a
时,并且由于理解是受List
的控制而知道它不能通过Option
时,它将把Option
转换为Iterable
,一切正常.
However, there is an implicit conversion from Option
to Iterable
. That being the case, when Scala finds b <- a
in the first example, and knowing it can't pass an Option
because the comprehension is being "controlled" by a List
, it converts the Option
into an Iterable
, and everything works.
但是,在第二种情况下不会发生这种情况.用Option
进行理解是可以的,因此无需将其转换为Iterable
.不幸的是,不能将List
转换为Option
(这种转换的结果是什么?),所以会导致错误.
However, that doesn't happen in the second case. Doing a for comprehension with an Option
is ok, so there's no need to convert it into an Iterable
. Unfortunately, one cannot convert a List
into an Option
(what would be the result of such a conversion?), which results in the error.
Scala不会回溯"到a <- Some(List(1, 2))
并对其进行隐式转换,因为Scala中的类型推断只会继续进行-之前决定的内容将保持不变.
Scala will not "backtrack" to a <- Some(List(1, 2))
and apply an implicit conversion to it, as type inference in Scala only goes forward -- what it decided before will remain as is.
我衷心推荐您查看相关问题,并了解a for comprehension的翻译方式.
I heartily recommend you look at the related questions and understand how a for comprehension is translated.
这篇关于Scala中具有理解力的补救语法问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!