gpt4 book ai didi

scala - 如何使用 "extract"类型参数实例化另一个类

转载 作者:行者123 更新时间:2023-12-04 22:59:37 26 4
gpt4 key购买 nike

以下 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", "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, Int]((a: Int, b: Int) => a + b)

甚至更好:
val red = new ReducerComponent[MapOutput](_ + _)

这意味着很多事情:
  • 我想打字检查 MapOutput类型为 KeyVal[K, C] ,
  • 我想打字检查 Cf 中使用的类型相同,
  • 我还需要“提取”K为了实例化 mem ,以及来自 apply 的类型检查参数.

  • 要问很多吗? :) 我想写一些类似的东西
    class ReducerComponent[KeyVal[K,V]](f: (V, V) => V) {...}

    到时候我会实例化 ReducerComponent我只有 fMapOutput ,所以推断 V 是可以的。但后来我只有 KeyVal[K,V]作为来自类的类型参数,可以不同于 KeyVal[_,_] .

    如果您了解类型推断的工作原理,我知道我要问的问题可能很疯狂,但我不知道!而且我什至不知道什么是继续进行的好方法 --- 除了在我的高级代码中一直进行显式类型声明。我应该改变所有的架构吗?

    最佳答案

    只写一个简单的工厂:

    case class RC[M <: KeyVal[_, _]](){
    def apply[K,V](f: (V,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有合适的类型。这里使用隐性证据来捕捉 KV来自您的 M <: KeyVal[_, _] .

    附注上面的版本需要为您的 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

    更新。如果你想对 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) => V) = new ReducerComponent[K,V](f)
    }
    }

    但请记住, apply从你的问题仍然需要 KeyVal[K,V] .

    您也可以通过 KV进入一些类:
    class Builder[KV[_,_]] {
    case class RC[M <: KV[_, _]](){
    def factory[K,V](implicit ev: KV[K,V] =:= M) = new {
    def apply(f: (V,V) => V) = new ReducerComponent[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

    关于scala - 如何使用 "extract"类型参数实例化另一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29754283/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com