我有一些关于特征的方法:
Error while trying to load the project '/home/emma/Documents/My-App/My-App/My-App.csproj': Unknown ToolsVersion '15.0'
很遗憾,类型检查器中没有任何内容可以阻止您使用返回trait ResourceFactory[+R] {
def using[T](work: R => T): T
def usingAsync[T](work: R => Future[T]): Future[T]
}
的函数调用第一个using
方法。我希望编译器坚持第一种方法中Future
的类型不是T
,以防止出现错误 - 这可能吗?
由于
答案 0 :(得分:2)
您可以使用shapeless' <:!<
:
import scala.concurrent.Future
import shapeless._
trait ResourceFactory[+R] {
def using[T](work: R => T)(implicit ev: T <:!< Future[_]): T = ???
def usingAsync[T](work: R => Future[T]): Future[T] = ???
}
然后:
scala> val r = new ResourceFactory[Int] {}
r: ResourceFactory[Int] = $anon$1@effe6ad
// Compiles (the error is due to the use of ???)
scala> r.using(_.toString)
scala.NotImplementedError: an implementation is missing
// Doesn't compile
scala> r.using(Future.successful(_))
<console>:17: error: ambiguous implicit values:
both method nsubAmbig1 in package shapeless of type [A, B >: A]=> shapeless.<:!<[A,B]
and method nsubAmbig2 in package shapeless of type [A, B >: A]=> shapeless.<:!<[A,B]
match expected type shapeless.<:!<[scala.concurrent.Future[Int],scala.concurrent.Future[_]]
r.using(Future.successful(_))
答案 1 :(得分:0)
@implicitNotFound("You're returning a ${A}, which is asynchronous, which means the resource may be closed before you try and use it. Instead use usingAsync.")
final class NotFuture[A] private[ResourceFactoryTests]()
object NotFuture {
final class Proof[A] private[ResourceFactory]()
object Proof {
implicit def preventFuture1[A]: Proof[Future[A]] = ???
implicit def preventFuture2[A]: Proof[Future[A]] = ???
@inline implicit def allowAnythingElse[A]: Proof[A] = null
}
@inline implicit def apply[A: Proof]: NotFuture[A] = null
}
可以用作:
trait ResourceFactory[+R] {
def using[T: ResourceGuard](work: R => T): T
def usingAsync[T](work: R => Future[T]): Future[T]
}
这样做的好处是不必在每次实施方法时都添加隐式arg,但缺点是我是纯粹的货物结果 - 我不明白为什么它有效,尽管它似乎使用类似的原则来不成形。