为什么带有扩展方法的代码可以编译?
Why does the code with extension method compile?
我有两个功能:
override def build_url(dbType: DbDriverType, dbAddr: String, dbName: String): F[DbAddr] = dbType match {
case PostgresSql =>
Applicative[F].pure(DbAddr("jdbc:postgresql://" |+| dbAddr |+| "/" |+| dbName))
case _ => DbDriverError.raiseError[F, DbAddr]
}
override def get_db_driver(dbType: DbDriverType): F[DbDriver] = dbType match {
case PostgresSql =>
Applicative[F].pure(DbDriver("org.postgresql.Driver"))
case _ => Applicative.raiseError[F, DbDriver](DbDriverError)
}
第一个编译,第二个不编译。编译器抱怨:
[error] found : io.databaker.db.DbDriverError.type
[error] required: cats.ApplicativeError[F, _ >: cats.Applicative.type]
[error] case _ => Applicative.raiseError[F, DbDriver](DbDriverError)
在第一个函数上,我在 DbDriverError.raiseError[F, DbAddr]
上使用了扩展方法,而在第二个函数上没有。对我来说,应该是一样的。
有什么区别?
在第二种情况下 Applicative.raiseError[F, DbDriver](DbDriverError)
您正在 Applicative
compaion 对象上使用扩展方法。所以这个
Applicative.raiseError[F, DbDriver](DbDriverError)
实际上是这样
new ApplicativeErrorIdOps[F, Applicative.type](Applicative).raiseError[DbDriver](DbDriverError)(implicitly[ApplicativeError[F, Applicative.type]])
显然没有 ApplicativeError[F, Applicative.type]
实例,如果您的代码类似于@Luis Miguel Mejía Suárez 的 scastei,那么 ApplicativeError[F, Throwable]
的形式为 Sync[F]
。
在第一个示例中它起作用了,因为 DbDriverError.raiseError[F, DbAddr]
是执行
的扩展方法
new ApplicativeErrorIdOps[F, DbDriverError.type](DbDriverError).raiseError[DbAddr](DbDriverError)(implicitly[ApplicativeError[F, DbDriverError.type]])
假设object DbDriverError extends Exception
(或其他Throwable
)等于直接调用
implicitly[ApplicativeError[F, Throwable]].raiseError[DbAddr](DbDriverError)
这个隐式也可以采用 MonadError[F, Throwable]
、Sync[F]
或 ApplicativeError[F, Throwable]
的任何其他实现。由于同伴有召唤方法你可以写:
ApplicativeError[F, Throwable].raiseError[DbDriver](DbDriverError)
// not the same as
// Applicative.raiseError[F, DbDriver](DbDriverError)
// !!!
// See where are square brackets and type parameters!
// And the class doesn't even match!
TLDR:
Applicative[F].sth
(调用 Applicative.apply[F[_]](implicit a: Applicative[F]): Applicative[F]
与 Applicative.sth
不同(调用 Applicative
伴随对象上的 method/extension 方法,特别是如果我们需要一个方法来自未在 Applicative
上定义的 ApplicativeError
)。
我有两个功能:
override def build_url(dbType: DbDriverType, dbAddr: String, dbName: String): F[DbAddr] = dbType match {
case PostgresSql =>
Applicative[F].pure(DbAddr("jdbc:postgresql://" |+| dbAddr |+| "/" |+| dbName))
case _ => DbDriverError.raiseError[F, DbAddr]
}
override def get_db_driver(dbType: DbDriverType): F[DbDriver] = dbType match {
case PostgresSql =>
Applicative[F].pure(DbDriver("org.postgresql.Driver"))
case _ => Applicative.raiseError[F, DbDriver](DbDriverError)
}
第一个编译,第二个不编译。编译器抱怨:
[error] found : io.databaker.db.DbDriverError.type
[error] required: cats.ApplicativeError[F, _ >: cats.Applicative.type]
[error] case _ => Applicative.raiseError[F, DbDriver](DbDriverError)
在第一个函数上,我在 DbDriverError.raiseError[F, DbAddr]
上使用了扩展方法,而在第二个函数上没有。对我来说,应该是一样的。
有什么区别?
在第二种情况下 Applicative.raiseError[F, DbDriver](DbDriverError)
您正在 Applicative
compaion 对象上使用扩展方法。所以这个
Applicative.raiseError[F, DbDriver](DbDriverError)
实际上是这样
new ApplicativeErrorIdOps[F, Applicative.type](Applicative).raiseError[DbDriver](DbDriverError)(implicitly[ApplicativeError[F, Applicative.type]])
显然没有 ApplicativeError[F, Applicative.type]
实例,如果您的代码类似于@Luis Miguel Mejía Suárez 的 scastei,那么 ApplicativeError[F, Throwable]
的形式为 Sync[F]
。
在第一个示例中它起作用了,因为 DbDriverError.raiseError[F, DbAddr]
是执行
new ApplicativeErrorIdOps[F, DbDriverError.type](DbDriverError).raiseError[DbAddr](DbDriverError)(implicitly[ApplicativeError[F, DbDriverError.type]])
假设object DbDriverError extends Exception
(或其他Throwable
)等于直接调用
implicitly[ApplicativeError[F, Throwable]].raiseError[DbAddr](DbDriverError)
这个隐式也可以采用 MonadError[F, Throwable]
、Sync[F]
或 ApplicativeError[F, Throwable]
的任何其他实现。由于同伴有召唤方法你可以写:
ApplicativeError[F, Throwable].raiseError[DbDriver](DbDriverError)
// not the same as
// Applicative.raiseError[F, DbDriver](DbDriverError)
// !!!
// See where are square brackets and type parameters!
// And the class doesn't even match!
TLDR:
Applicative[F].sth
(调用 Applicative.apply[F[_]](implicit a: Applicative[F]): Applicative[F]
与 Applicative.sth
不同(调用 Applicative
伴随对象上的 method/extension 方法,特别是如果我们需要一个方法来自未在 Applicative
上定义的 ApplicativeError
)。