【发布时间】:2019-06-15 11:03:36
【问题描述】:
假设我正在尝试“抽象执行”:
import scala.language.higherKinds
class Operator[W[_]]( f : Int => W[Int] ) {
def operate( i : Int ) : W[Int] = f(i)
}
现在我可以定义Operator[Future] 或Operator[Task] 等。例如...
import scala.concurrent.{ExecutionContext,Future}
def futureSquared( i : Int ) = Future( i * i )( ExecutionContext.global )
REPL 风格...
scala> val fop = new Operator( futureSquared )
fop: Operator[scala.concurrent.Future] = Operator@105c54cb
scala> fop.operate(4)
res0: scala.concurrent.Future[Int] = Future(<not completed>)
scala> res0
res1: scala.concurrent.Future[Int] = Future(Success(16))
万岁!
但我也可能想要一个简单的同步版本,所以我在某个地方定义
type Identity[T] = T
而且我可以定义一个同步操作符...
scala> def square( i : Int ) : Identity[Int] = i * i
square: (i: Int)Identity[Int]
scala> val sop = new Operator( square )
sop: Operator[Identity] = Operator@18f2960b
scala> sop.operate(9)
res2: Identity[Int] = 81
甜。
但是,结果的推断类型是Identity[Int],而不是更简单、直接的Int,这很尴尬。当然,这两种类型实际上是相同的,因此在各方面都是相同的。但我希望我的图书馆的客户不要对这种抽象过度执行的东西一无所知。
我可以手写一个包装器...
class SimpleOperator( inner : Operator[Identity] ) extends Operator[Identity]( inner.operate ) {
override def operate( i : Int ) : Int = super.operate(i)
}
确实有效...
scala> val simple = new SimpleOperator( sop )
simple: SimpleOperator = SimpleOperator@345c744e
scala> simple.operate(7)
res3: Int = 49
但是这感觉很像样板,特别是如果我的抽象过度执行类有很多方法,而不仅仅是一个。而且我必须记住随着泛型类的发展保持包装器同步。
是否有一些更通用、可维护的方法来获得一个版本的 Operator[Identity] 以使包含类型从类型推断和 API 文档中消失?
【问题讨论】:
标签: scala