【发布时间】:2019-06-30 23:14:53
【问题描述】:
假设我为缓存计算定义了一个类型类。
trait Cached[F[_], A] {
def value: F[A]
}
直观地说,Cached 封装了计算,因此我们可以在运行时对其进行评估,也可以从数据库中加载结果。
我想为此特征定义 Functor、Applicative 和 Monad 实例。使用 Kind-projector 让我的生活更轻松:
import scalaz._, Scalaz._
object Cached {
def apply[F[_], A](f: => F[A]): Cached[F, A] = new Cached[F, A] {
override def value: F[A] = f
}
implicit def functor[F[_] : Functor]: Functor[Cached[F, ?]] = new Functor[Cached[F, ?]] {
override def map[A, B](fa: Cached[F, A])(f: A => B): Cached[F, B] =
Cached(fa.value map f)
}
implicit def applicative[F[_] : Applicative]: Applicative[Cached[F, ?]] = new Applicative[Cached[F, ?]] {
override def point[A](a: => A): Cached[F, A] = Cached(a.point[F])
override def ap[A, B](fa: => Cached[F, A])(f: => Cached[F, A => B]): Cached[F, B] =
Cached(fa.value <*> f.value)
}
implicit def monad[F[_] : Monad](implicit app: Applicative[Cached[F, ?]], func: Functor[Cached[F, ?]]): Monad[Cached[F, ?]] =
new Monad[Cached[F, ?]] {
override def point[A](a: => A): Cached[F, A] = app.point(a)
override def bind[A, B](fa: Cached[F, A])(f: A => Cached[F, B]): Cached[F, B] =
Cached(func.map(fa)(f).value >>= (_.value))
}
}
到目前为止,一切都很好。现在,让我们在一个简单的例子中使用 monad:
import Cached._
val y = Cached(2.point[Id])
val z = for {
a <- Cached(1.point[Id])
b <- y
} yield a + b
运行代码,运行时出现如下错误:
[error] diverging implicit expansion for type scalaz.Applicative[[β$4$]Cached[scalaz.Scalaz.Id,β$4$]]
[error] starting with method monad in object Cached
[error] a <- Cached(1.point[Id])
[error] ^
[error] diverging implicit expansion for type scalaz.Applicative[[β$4$]Cached[scalaz.Scalaz.Id,β$4$]]
[error] starting with method monad in object Cached
[error] b <- y
[error] ^
[error] two errors found
[error] (Test / compileIncremental) Compilation failed
我知道当编译器在扩展隐式定义时陷入循环时会发生发散隐式扩展,但我不明白为什么我的代码会出现这种情况。
如果有人能指出我正确的方向,我将不胜感激。我对函数式编程概念很陌生,所以我在这里所做的可能甚至没有意义!
【问题讨论】:
标签: scala functional-programming scalaz