我有以下(工作)代码
val superSuperSorts = superSorts.flatMap(relations.get(_)).flatMap(x=>x)
我给你这里的类型
val superSorts: Set[Sort]
val relations: Map[Sort, Set[Sort]]
将其更改为此for-comprehension会给我一个编译错误
val superSuperSorts =
for(
ss <- superSorts;
sss <- relations.get(ss); //get Option[Set[Sort]] and flatten the option
s <- sss //extract the elements from the Set
) yield s
这个阅读
error: type mismatch;
found : scala.collection.immutable.Set[edu.uulm.scbayes.logic.Sort]
required: Option[?]
s <- sss
请解释为什么我的理解错误。
答案 0 :(得分:8)
您不能flatMap
选项。看看它的类型签名:
def flatMap [B] (f: (A) ⇒ Option[B]): Option[B]
因此,flatMap
解压缩选项,但需要一个新的选项,因此您需要一个替代方案。您可以使用Map的方法getOrElse
或选项的方法seq
:
val superSuperSorts = for {
s <- superSorts
ss <- relations.getOrElse(s, Set.empty)
} yield s
val superSuperSorts = for {
s <- superSorts
ss <- relations.get(s).seq
sss <- ss
} yield sss
另一个问题是,您的flatMap
代码与您的for-expression不同。表达式
for (x <- expr1; y <- expr2) yield expr3
被翻译为
expr1.flatMap(x => for (y <- expr2) yield expr3)
并在另一步
expr1.flatMap(x => expr2.map(y => expr3))
但你有:
expr1.flatMap(x => expr2).flatMap(y => expr3)
答案 1 :(得分:1)
让我举一个例子来说明问题所在。假设你有:
val superSorts = Set('x)
val relations = Map('x -> Set('a, 'b))
此代码:
val superSuperSorts =
for(
ss <- superSorts;
sss <- relations.get(ss); //get Option[Set[Sort]] and flatten the option
s <- sss //extract the elements from the Set
) yield s
转换为:
superSorts.flatMap(
ss => relations.get(ss).flatMap(
sss => sss.map(
s => s)))
首先,请注意,上一个字词是map
,而不是flatMap
。现在,让我们考虑使用上面的数据进行迭代:
ss = 'x
sss = Set('a, 'b)
s = 'a, 'b
现在让我们回到代码中。
// Set('a, 'b) => Set('a, 'b)
sss.map(s => s)
// Some(Set('a, 'b)) => Some('a, 'b)????
relations.get(ss).flatMap(...)
在这里查看问题? Option[Set[Sort]]
怎样才能被夷为平地?没有Some('a, 'b)
这样的东西。
那么,为什么原始代码有用呢?
val superSuperSorts = superSorts.flatMap(relations.get(_)).flatMap(x=>x)
如果我们将其分解:
// Set('x) => Set(Set('a, 'b))
superSorts.flatMap(relations.get(_))
// Set(Set('a, 'b')) => Set('a, 'b)
(...).flatMap(x=>x)
了解flatMap
是如何应用Set
而不是Option
的? Option
已被flatMap
淘汰,但从未发挥过作用。
您的代码或多或少等同于理解:
val superSuperSorts = for {
x <- (for {
ss <- superSorts
sss <- relations.get(ss)
} yield sss)
s <- x
} yield s
这引入了一些身份地图:map(sss => sss)
和map(s => s)
,它们解决了for-comprehension中的最后一个生成器始终为map
的事实。
答案 2 :(得分:0)
重要的是要理解一个for comprehension会产生所输入的集合类型。那么为什么你的代码不起作用你想要返回一个元素。试试这个:
val superSuperSorts =
for(
ss <- superSorts;
sss <- relations.get(ss); //get Option[Set[Sort]] and flatten the option
) yield sss
:/希望这会有所帮助