我正在学习Functor[F[_]]
s。我想为我想映射集合中的“叶”元素的所有情况提供隐式仿函数。
例如给定的实例:
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)))
现在,如果我想使用 Functor 映射元素,我需要提供他们的实例:
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)
在这一点上,由于缺少隐式(如预期的那样),下面将不起作用:
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
我可以通过提供组合的 Functor 来简单地修复它:
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]
...嗯 - 这看起来有点像样板,不是吗?
尝试成为一个聪明的开发人员,我发现如果我只是使用某种递归风格来提供所有这些 Functor,那么它可能会有所帮助。这是我开发的:
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
。
我认为这autoComposedFunctor[List, Option]
将提供类型的隐式范围值,Functor[List[Option]]
因此下次可以通过使用Functor[Option[List[Option]]]
先前提供的实例调用相同的函数来获取并使用它来提供。但是id没有。
任何想法为什么?
(scalaVersion 是“2.11.6”)