这是我之前的后续question https://stackoverflow.com/questions/28850636/example-of-applicative-composition-in-scala在互联网上找到一个例子。
假设我定义了一个类型类Applicative
如下:
trait Functor[T[_]]{
def map[A,B](f:A=>B, ta:T[A]):T[B]
}
trait Applicative[T[_]] extends Functor[T] {
def unit[A](a:A):T[A]
def ap[A,B](tf:T[A=>B], ta:T[A]):T[B]
}
我可以定义一个实例Applicative
for List
object AppList extends Applicative[List] {
def map[A,B](f:A=>B, as:List[A]) = as.map(f)
def unit[A](a: A) = List(a)
def ap[A,B](fs:List[A=>B], as:List[A]) = for(f <- fs; a <- as) yield f(a)
}
为了方便起见,我可以定义一个implicit conversion
添加一个方法<*>
to List[A=>B]
implicit def toApplicative[A, B](fs: List[A=>B]) = new {
def <*>(as: List[A]) = AppList.ap(fs, as)
}
现在我可以做一件很酷的事情了!
压缩两个列表List[String]
并申请f2
到每一对应用性的 style
val f2: (String, String) => String = {(first, last) => s"$first $last"}
val firsts = List("a", "b", "c")
val lasts = List("x", "y", "z")
scala> AppList.unit(f2.curried) <*> firsts <*> lasts
res31: List[String] = List(a x, a y, a z, b x, b y, b z, c x, c y, c z)
到目前为止,一切都很好,但现在我有:
val firstsOpt = Some(firsts)
val lastsOpt = Some(lasts)
我想要拉链firsts
and lasts
, apply f2
,并得到Option[List[String]]
in 应用性的风格。换句话说我需要<*>
for Option[List[_]]
。我该怎么做 ?