Это продолжение моего предыдущего вопроса с примером, найденным в Интернете.
Предположим, я определяю класс типов 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
для 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
, чтобы добавить метод <*>
к List[A=>B]
implicit def toApplicative[A, B](fs: List[A=>B]) = new {
def <*>(as: List[A]) = AppList.ap(fs, as)
}
Теперь я могу сделать классную вещь!
сжать два списка List[String]
и применить f2
к каждой паре в аппликативном стиле.
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
и lasts
, применить f2
и получить Option[List[String]]
в аппликативном стиле. Другими словами, мне нужно <*>
для Option[List[_]]
. Как мне это сделать ?