你要的AmazingMalini
簽名更改爲trait AmazingMalini[F[_], G[_]]
方法,然後可以像這樣實現的:
trait AmazingMalini[F[_], G[_]] {
def fMap[A,B](aa: F[G[A]])(f : A => F[G[B]]) : F[G[B]]
}
trait SomeCrazyMagicWithList extends AmazingMalini[Option, List] {
def fMap[A, B](aa: Option[List[A]])(f: A => Option[List[B]]): Option[List[B]] =
aa.flatMap {
_ match {
case Nil => Some(Nil)
case as: List[A] => as.map(f).reduce(concat(_, _))
}
}
def concat[A](x: Option[List[A]], y: Option[List[A]]): Option[List[A]] = for {
xs <- x
ys <- y
} yield xs ++ ys
}
注意Scalaz提供monad transformers,使某些單子的堆疊。例如:
- 的
OptionT
變壓器使上的Option
頂部任何單子的堆疊:List[Option[A]]
,Future[Option[A]]
等
- 的
ListT
變壓器使上的List
頂部任何單子的堆疊:Option[List[A]]
,Future[List[A]]
。
所以,你的情況,你可以使用ListT
這樣的:
import scalaz._
import Scalaz._
import ListT._
listT(List(1,2,3).some).flatMap(i => listT(List(i, i * 3).some))
res0: scalaz.ListT[Option,Int] = ListT(Some(List(1, 3, 2, 6, 3, 9)))
您也可以使用,內涵與單子變壓器:
for {
x <- listT(List(1,2).some)
y <- listT(List(3,4).some)
} yield x + y
res2: scalaz.ListT[Option,Int] = ListT(Some(List(4, 5, 5, 6)))
我不知道這是正確的解決方案,但似乎工作:'特質AmazingMalini [F [G],G [_]]','特質SomeCrazyMagicWithList延伸AmazingMalini [Option,List]'。其餘代碼不變。 –
我會避免使用相同的標識符'G'作爲不同的事情,這是相當混亂。換句話說,最好是'AmazingMalini [F [_],G [_]]' –