用于理解部分功能

时间:2014-06-17 20:34:43

标签: scala

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 
 }
}

我理解formap有什么看法,但为什么会起作用?

1 个答案:

答案 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