什么时候进行类型检查以进行理解?

When is type checking done in for comprehension?

关于使用 mapflatMapwithFilterfor 表达式进行脱糖的主题,Programming In Scala 3rd Ed 一书 说(在“重新访问表达式”一章中)

The translation of for expressions happens before type checking. This allows for maximum flexibility because the only requirement is that the result of expanding a for expression type checks.

但是,在 REPL 中,

for (x: Int <- List("a", "b")) yield x

给予

<console>:12: error: scrutinee is incompatible with pattern type;  
 found   : Int  
 required: String  
       for(x: Int <- List("a", "b")) yield x  
              ^

同样,

for(x <- List("a", "b")) yield math.pow(x, 2)

给予

<console>:12: error: type mismatch;
 found   : String
 required: Double
       for(x <- List("a", "b")) yield math.pow(x, 2)
                                               ^

在我看来,这似乎与书中的内容相矛盾,因为它似乎在脱糖之前进行了类型检查。也许...

我相信你的第二个建议是正确的。这两种类型的错误都发生在翻译之后,但是如果编译器在给您错误时将您指向某些生成的代码,那将是非常烦人的。想象一下它给出了这条消息:

<console>:12: error: type mismatch;
 found   : String
 required: Double
       List("a", "b").map(x => math.pow(x, 2))
                                        ^

然后你必须坐在那里思考这段代码是什么——你没有编写任何对 map 的调用或任何类似的匿名函数。如果 for-comprehension 更复杂,情况会更糟 10 倍,并导致多个嵌套的 flatMaps 和 withFilters 等等。因此,它会将您指向您实际编写的预转换版本。