Scala 单子的通用“隐式”运算符?
这部分是编程练习,部分是实践 在本例中,我希望构建一个操作符Scala 单子的通用“隐式”运算符?,scala,operators,implicit-conversion,typeclass,implicit,Scala,Operators,Implicit Conversion,Typeclass,Implicit,这部分是编程练习,部分是实践 在本例中,我希望构建一个操作符|,以便: val x: Option[Int] = _ def fail: Nothing = _ val result = x | fail 到目前为止,我有这个,但它没有编译: import language.implicitConversions import scala.util.{Try, Success, Failure} trait OrAbleFacilitator[T] { def apply[U](t:
|
,以便:
val x: Option[Int] = _
def fail: Nothing = _
val result = x | fail
到目前为止,我有这个,但它没有编译:
import language.implicitConversions
import scala.util.{Try, Success, Failure}
trait OrAbleFacilitator[T] {
def apply[U](t: T, u: => U): U
}
implicit val OptionOrAbleFacilitator = new OrAbleFacilitator[Option[T]] {
def apply[U, U >: T](t: Option[T], u: => U): U = {
t match {
case Some(v) => v
case _ => u
}
}
}
implicit val TryOrAbleFacilitator = new OrAbleFacilitator[Try[T]] {
def apply[U, U >: T](t: Try[T], u: => U): U = {
t match {
case Success(v) => v
case _ => u
}
}
}
implicit class OrAble[T](t: T) {
def |[U](u: => U)(implicit orFacilitator: OrAbleFacilitator[T, U]): U = {
orFacilitator(t, u)
}
}
我做错了什么?为了让事情顺利进行,我移动了一堆小东西。我试着对大多数地方进行评论,我做了一些更改,以使其运行
import language.implicitConversions
import scala.util.{Try, Success, Failure}
// you need to wrap this all in an object, since you can't have vals at the top level
object Main extends App {
// you need to capture in the trait that you are abstracting of a
// * → * kind, that is to say it needs to be a type which takes a type
// as input and returns you a type, such as Option or Try or List.. The thing you are creating an
// orable for is going to have to be in the shape F[A], not just F,
// and there is no reason to fix the inner type
trait OrAbleFacilitator[F[_]] {
// the first parameter to apply needs to be F[T], and the return type must be a supertype of T
def apply[T, U >: T](t: F[T], u: => U): U
}
implicit val OptionOrAbleFacilitator = new OrAbleFacilitator[Option] {
// here we need to accept the types for the input and output, adn they must be realted
def apply[T, U >: T](t: Option[T], u: => U): U = {
t match {
case Some(v) => v
case _ => u
}
}
}
implicit val TryOrAbleFacilitator = new OrAbleFacilitator[Try] {
def apply[T, U >: T](t: Try[T], u: => U): U = {
t match {
case Success(v) => v
case _ => u
}
}
}
// we can't just wrap any old T, it has to be something in the shape
// F[T] moved the implcit up to where we create the class so that it
// doesn't cuase us to have an additional parameter list on our |
// function ( which would prevent us from using it inline )
implicit class OrAble[F[_], T](t: F[T])(implicit or: OrAbleFacilitator[F]) {
// the vertical bar | is already a keyword in scala, I used the formal "disjunction" operatior (|) instead.
def |[U >: T](u: => U): U = {
or(t, u)
}
}
// and it works:
val noneint: Option[Int] = None
val failint: Try[Int] = Failure(new Exception())
assert((Some(0) : Option[Int]) .|(Some(1)) == 0)
assert((noneint | 2) == 2)
assert(((Success(0) : Try[Int]) | 3) == 0)
assert((failint | 4) == 4)
}