加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 如何“提取”类型参数来实例化另一个类

发布时间:2020-12-16 09:27:42 所属栏目:安全 来源:网络整理
导读:以下Scala代码有效: object ReducerTestMain extends App { type MapOutput = KeyVal[String,Int] def mapFun(s:String): MapOutput = KeyVal(s,1) val red = new ReducerComponent[String,Int]((a: Int,b: Int) = a + b) val data = List[String]("a","b",
以下Scala代码有效:

object ReducerTestMain extends App {

  type MapOutput = KeyVal[String,Int]

  def mapFun(s:String): MapOutput = KeyVal(s,1)

  val red = new ReducerComponent[String,Int]((a: Int,b: Int) => a + b)

  val data = List[String]("a","b","c","b")

  data foreach {s => red(mapFun(s))}
  println(red.mem)
  // OUTPUT: Map(a -> 1,b -> 3,c -> 2)
}

class ReducerComponent[K,V](f: (V,V) => V) {
  var mem = Map[K,V]()

  def apply(kv: KeyVal[K,V]) = {
    val KeyVal(k,v) = kv
    mem += (k -> (if (mem contains k) f(mem(k),v) else v))
  }
}

case class KeyVal[K,V](key: K,value:V)

我的问题是我想像这样实例化ReducerComponent:

val red = new ReducerComponent[MapOutput,b: Int) => a + b)

甚至更好:

val red = new ReducerComponent[MapOutput](_ + _)

这意味着很多事情:

>我想键入 – 检查MapOutput的类型是KeyVal [K,C],
>我想要输入 – 检查C是否与f中使用的类型相同,
>我还需要“提取”K以实例化mem,并从apply中输入类型检查参数.

要问很多吗? :)我想写点类似的东西

class ReducerComponent[KeyVal[K,V]](f: (V,V) => V) {...}

当我将实例化ReducerComponent时,我只有f和MapOutput,所以推断V是可以的.但后来我只将KeyVal [K,V]作为类中的类型参数,它可以与KeyVal [_,_]不同.

我知道如果你理解类型推理是如何工作的,我问的可能是疯了,但我不知道!我甚至不知道什么是一个好的方法继续 – 除了在我的高级代码中一直提出明确的类型声明.我应该改变所有的架构吗?

解决方法

写一个简单的工厂:

case class RC[M <: KeyVal[_,_]](){
   def apply[K,V) => V)(implicit ev: KeyVal[K,V] =:= M) = new ReducerComponent[K,V](f)
}

def plus(x: Double,y: Double) = x + y

scala> RC[KeyVal[Int,Double]].apply(plus)
res12: ReducerComponent[Int,Double] = ReducerComponent@7229d116

scala> RC[KeyVal[Int,Double]]()(plus)
res16: ReducerComponent[Int,Double] = ReducerComponent@389f65fe

如您所见,ReducerComponent具有适当的类型.这里使用隐式证据从M<:KeyVal [_,_]中捕获K和V. 附:上面的版本要求为f明确指定参数类型,如(_:Double)(_:Double).如果你想避免这种情况:

case class RC[M <: KeyVal[_,_]](){
   def factory[K,V](implicit ev: KeyVal[K,V] =:= M) = new {
      def apply(f: (V,V) => V) = new ReducerComponent[K,V](f)
   }
}

scala> RC[KeyVal[Int,Double]].factory.apply(_ + _)
res5: ReducerComponent[Int,Double] = ReducerComponent@3dc04400 


scala> val f = RC[KeyVal[Int,Double]].factory
f: AnyRef{def apply(f: (Double,Double) => Double): ReducerComponent[Int,Double]} = RC$$anon$1@19388ff6

scala> f(_ + _)
res13: ReducerComponent[Int,Double] = ReducerComponent@24d8ae83

更新.如果你想generelize keyval – 使用类型函数:

type KV[K,V] = KeyVal[K,V] //may be anything,may implement `type KV[K,V]` from some supertrait

case class RC[M <: KV[_,_]](){   
  def factory[K,V](implicit ev: KV[K,V] =:= M) = new {
    def apply(f: (V,V](f)
  }
}

但请记住,从您的问题中应用仍然需要KeyVal [K,V].

您还可以将KV传递到某个类:

class Builder[KV[_,_]] {
  case class RC[M <: KV[_,_]](){   
    def factory[K,V](f)
    }
  }
}

scala> val b = new Builder[KeyVal]
scala> val f = b.RC[KeyVal[Int,Double]].factory
scala> f(_ + _)
res2: ReducerComponent[Int,Double] = ReducerComponent@54d9c993

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读