4

我正在学习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”)

4

0 回答 0