我正在学习Functor[F[_]]
s。我想为我想要映射的所有情况提供隐式函数' leaf'集合中的元素。
例如给定的实例:
val collection0 = List(1,2,3)
val collection1 = List(Some(1))
val collection2 = List(List(Some(2)))
val collection3 = Option(List(Some(3), None, Some(0)))
现在,如果我想使用Functors映射元素,我需要提供他们的实例:
import cats.Functor //scalaz can be used here instaed
import cats.std.option._ //this brings Functor[Option] into scope
import cats.std.list._ //and this brings Functor[List] into scope
这将有效:
Functor[List].map(collection0)(_ + 1)
此时由于缺少implicits(如预期的那样),下面将无效:
type LO[X] = List[Option[X]]
Functor[LO].map(collection1) (_ + 1) //could not find implicit value for parameter instance: cats.Functor[LO]
type LLO[X] = List[List[Option[X]]]
Functor[LLO].map(collection2) (_ + 1) //ditto
type OLO[X] = Option[List[Option[X]]]
Functor[LLO].map(collection2) (_ + 1) //ditto
我可以通过提供组合的Functors来简单地修复它:
implicit val loFunctor = Functor[List] compose Functor[Option]
implicit val lloFunctor = Functor[List] compose Functor[List] compose Functor[Option]
implicit val oloFunctor = Functor[Option] compose Functor[List] compose Functor[Option]
......好吧 - 这看起来有点像样板,不是吗?
尝试成为一个聪明的开发人员我发现如果我只是使用一些提供所有这些Functors的递归样式,那么它会提供帮助。这就是我开发的:
import scala.language.higherKinds
implicit def autoComposedFunctor[A[_] : Functor, B[_] : Functor]: Functor[Lambda[a => A[B[a]]]] = Functor[A] compose Functor[B]
//or the same without kind projector support:
implicit def autoComposedFunctor[A[_] : Functor, B[_] : Functor]: Functor[({type L[X] = A[B[X]]})#L] = Functor[A] compose Functor[B]
它几乎正常运作。至少对于collection1
,但它没有为collection2
和collection3
的示例提供隐式Functor。
我认为autoComposedFunctor[List, Option]
将提供Functor[List[Option]]
类型的隐式作用域值,以便下次可以通过调用与先前提供的实例相同的函数来提取Functor[Option[List[Option]]]
。但是id并没有。
任何想法为什么?
(scalaVersion是" 2.11.6")