def testDef ={
val strMap = scala.collection.mutable.Map[Int,String]()
strMap.map{
case (k,v) => for{
d <- MyDAO.findById(k) //d is an Entity of some Type T. findById returns Option[T]
field <- extract(d.address) //field is a String
} yield field
}
}
我的理解是,当使用for
理解时,第一个生成器类型决定了yield
结果的类型。例如在上述情况d
中,某种类型T
认为必须从yield
for
理解for
。
case
理解(使用yield
)的上述特殊用法可以正常工作,但我感到困惑,因为我能够T
任何类型的&#34;事物&#34;。例如我认为,因为第一个生成器属于yield
某种类型,我唯一可以yield
,但我也可以field
String
,类型为{ {1}}。并且不仅可以yield
String
,还可以为了这个例子,下面也是如此。
case class Person
def test(person:Person) ={
val strMap = scala.collection.mutable.Map[Int,String]()
strMap.map{
case (k,v) => for{
d <- MyDAO.findById(k) //d is an Entity of some Type T. findById returns Option[T]
field <- extract(d.address) //field is a String
} yield person
}
}
我理解for
对map
有什么看法,但为什么会起作用?
答案 0 :(得分:4)
因为理解必须适用于兼容的 monads ,而不是类型参数。
for (x <- xs; y <- ys(x)) yield f(y)
desugars to
xs.flatMap{ x => ys(x).map(f(y)) }
所以xs
最好有flatMap
,可以采取任何ys(x).map(f(y))
吐出来。
通常,课程flatMap
上的M[A]
签名看起来像flatMap[B](f: A => M[B]): M[B]
。所以,只要外部和内部容器是相同的类型(例如Option
),每个人都很高兴。存储的类型(首先A
,然后是B
)根本不重要,除非容器M
只能采用某些类型,并且您尝试使其保留一些内容吨。
此外,如果内部容器可以被强制转换为外部形式,那么每个人都很高兴(例如,隐含地将Option
转换为Seq
,所以你可以做{ {1}}。
如果尝试容器形状不同的东西,它将无效。例如:
List("fish", null).flatMap(x => Option(x))
抱怨需要for (x <- Option("fish"); y <- List(x,x)) yield y
。