泛型类型边界问题
Issue with generic type bounds
我有以下特点:
trait Recoverable[M[_]] {
def recoverW[T, U >: T](f: PartialFunction[Throwable, M[U]])(implicit executor: ExecutionContext): M[U]
def fail[T](error: Throwable): M[T]
}
我在同一个包中还有一个隐式转换方法:
implicit def tryRecoverable[T](`try`: Try[T]) = new Recoverable[Try] {
override def recoverW[T, U >: T](f: PartialFunction[Throwable, Try[U]])(implicit executor: ExecutionContext): Try[U] = `try`.recoverWith[U](f)
override def fail[T](error: Throwable): Try[T] = Failure(error)
}
此代码无法编译,抱怨
type arguments [U] do not conform to method recoverWith's type parameter bounds [U >: T]
override def recoverW[T, U >: T](f: PartialFunction[Throwable, Try[U]])(implicit executor: ExecutionContext): Try[U] = `try`.recoverWith[U](f)
^
为什么这段代码无法编译?
因为 recoverW
中的 T
和 tryRecoverable
中的 T
- 是不同的 T([T, ...]
定义了新的方法范围 T
) , 你可以:
trait Recoverable[M[_]] {
type TT
def recoverW[U >: TT](f: PartialFunction[Throwable, M[U]])(implicit executor: ExecutionContext): M[U]
def fail(error: Throwable): M[TT]
}
implicit def tryRecoverable[T](`try`: Try[T]) = new Recoverable[Try] {
type TT = T
override def recoverW[U >: T](f: PartialFunction[Throwable, Try[U]])(implicit executor: ExecutionContext): Try[U] = `try`.recoverWith[U](f)
override def fail(error: Throwable): Try[T] = Failure(error)
}
但我不会在这里使用 M[_]
定义,因为它主要用于当您可以在方法中实际具体化 M[_]
时,例如:
trait Monad[M[_]] extends Applicative[M] {
def flatMap[T, U](m: M[T])(fn: (T) => M[U]): M[U]
...
}
例如,请参阅 Twitter 的 Monad。实际上,使用 M[_]
更像是 Haskell 风格,因为没有类,所以 monad 本身作为参数传递给方法。所以也许你根本不应该使用它并直接指定 trait Recoverable[M[T]]
。
或者你也可以Haskell风格:
trait Recoverable[M[_]] {
def recoverW[T, U >: T](m: M[T])(f: PartialFunction[Throwable, M[U]])(implicit executor: ExecutionContext): M[U]
def fail[T](m: M[T])(error: Throwable): M[T]
}
implicit val tryRecoverable = new Recoverable[Try] {
override def recoverW[T, U >: T](`try`: Try[T])( f: PartialFunction[Throwable, Try[U]])(implicit executor: ExecutionContext): Try[U] = `try`.recoverWith[U](f)
override def fail[T](`try`: Try[T])( error: Throwable): Try[T] = Failure(error)
}
然后将其用作:
scala> implicitly[Recoverable[Try]].recoverW(Try{"aaaa"})({case x => Try{"bbb"}})
res54: scala.util.Try[String] = Success(aaaa)
或者使用 Try[T]: Recoverable
语法糖在 function/class 中要求它:
def recover[T, Try[T]: Recoverable](t: Try[T]) = recoverW(t) _
我有以下特点:
trait Recoverable[M[_]] {
def recoverW[T, U >: T](f: PartialFunction[Throwable, M[U]])(implicit executor: ExecutionContext): M[U]
def fail[T](error: Throwable): M[T]
}
我在同一个包中还有一个隐式转换方法:
implicit def tryRecoverable[T](`try`: Try[T]) = new Recoverable[Try] {
override def recoverW[T, U >: T](f: PartialFunction[Throwable, Try[U]])(implicit executor: ExecutionContext): Try[U] = `try`.recoverWith[U](f)
override def fail[T](error: Throwable): Try[T] = Failure(error)
}
此代码无法编译,抱怨
type arguments [U] do not conform to method recoverWith's type parameter bounds [U >: T]
override def recoverW[T, U >: T](f: PartialFunction[Throwable, Try[U]])(implicit executor: ExecutionContext): Try[U] = `try`.recoverWith[U](f)
^
为什么这段代码无法编译?
因为 recoverW
中的 T
和 tryRecoverable
中的 T
- 是不同的 T([T, ...]
定义了新的方法范围 T
) , 你可以:
trait Recoverable[M[_]] {
type TT
def recoverW[U >: TT](f: PartialFunction[Throwable, M[U]])(implicit executor: ExecutionContext): M[U]
def fail(error: Throwable): M[TT]
}
implicit def tryRecoverable[T](`try`: Try[T]) = new Recoverable[Try] {
type TT = T
override def recoverW[U >: T](f: PartialFunction[Throwable, Try[U]])(implicit executor: ExecutionContext): Try[U] = `try`.recoverWith[U](f)
override def fail(error: Throwable): Try[T] = Failure(error)
}
但我不会在这里使用 M[_]
定义,因为它主要用于当您可以在方法中实际具体化 M[_]
时,例如:
trait Monad[M[_]] extends Applicative[M] {
def flatMap[T, U](m: M[T])(fn: (T) => M[U]): M[U]
...
}
例如,请参阅 Twitter 的 Monad。实际上,使用 M[_]
更像是 Haskell 风格,因为没有类,所以 monad 本身作为参数传递给方法。所以也许你根本不应该使用它并直接指定 trait Recoverable[M[T]]
。
或者你也可以Haskell风格:
trait Recoverable[M[_]] {
def recoverW[T, U >: T](m: M[T])(f: PartialFunction[Throwable, M[U]])(implicit executor: ExecutionContext): M[U]
def fail[T](m: M[T])(error: Throwable): M[T]
}
implicit val tryRecoverable = new Recoverable[Try] {
override def recoverW[T, U >: T](`try`: Try[T])( f: PartialFunction[Throwable, Try[U]])(implicit executor: ExecutionContext): Try[U] = `try`.recoverWith[U](f)
override def fail[T](`try`: Try[T])( error: Throwable): Try[T] = Failure(error)
}
然后将其用作:
scala> implicitly[Recoverable[Try]].recoverW(Try{"aaaa"})({case x => Try{"bbb"}})
res54: scala.util.Try[String] = Success(aaaa)
或者使用 Try[T]: Recoverable
语法糖在 function/class 中要求它:
def recover[T, Try[T]: Recoverable](t: Try[T]) = recoverW(t) _