【问题标题】:Implicit values of generic types for implicit parameters in scalascala中隐式参数的泛型类型的隐式值
【发布时间】:2014-02-27 17:28:35
【问题描述】:

我有一个方法:

def pollAll[T, O](orchestrators :Seq[O], poll :(O)=>Future[T])
                 (implicit reduce: (T, T) => T) :Future[T] =
(Future sequence orchestrators.map(poll(_))).map(res => res.reduce(reduce))

现在,假设我有一个返回 Future[Seq[A]] 的投票。是否有可能为reduce 参数提供一个通用的隐式值,它将任何两个具有共同元素类型的序列连接起来?像这样的:

implicit def reduceSeq[T] = (s1 :Seq[T], s2 :Seq[T]) => s1 ++ s2

上面的不行,因为隐式方法用于隐式转换,在查找隐式参数时不考虑其结果。

【问题讨论】:

  • 如果 T 不是 Seq 怎么办?你不会错过 T 上的类型吗?
  • 好吧,当然,如果 pollAll 中的 T 不是 Seq,那么隐式参数将没有任何值,除非我定义了一个特定的参数。
  • 方法调用 "pollAll(List.empty[Int], (i:Int) => future(Seq(i)))" 与您的隐式声明编译对我来说没有任何错误。我在这里错过了什么吗?
  • 如果我尝试运行 pollAll(orchestrators, poll)(其中 orchestrators :Seq[Orchestrator]`,编译器会抱怨找不到 reduce 参数的隐式值。这是正确的,因为隐式方法仅用于隐式转换,而不是作为默认参数的提供者。

标签: scala generics implicit


【解决方案1】:

我也没有发现您的解决方案有任何问题,但是 scalaz 定义了称为 SemigroupMonoid 的类型,这可以帮助您。它还包括许多常见类型的Semigroup 定义,例如ListIntSemiGroup 定义了一个 append 操作。 Monoid 扩展了 Semigroup,但另外提供了 zero 或初始值。如果orchestrators 可以为空,这将很有用,在这种情况下,您需要foldLeft 而不是reduce

注意:我颠倒了你的类型参数

import scalaz._
import Scalaz._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def pollAll[O, T : Semigroup](orchestrators :Seq[O], poll :(O)=>Future[T]) :Future[T] = 
 (Future sequence orchestrators.map(poll(_)))
   .map(res => res.reduce(implicitly[Semigroup[T]].append(_, _)))

或加糖

def pollAll2[O, T : Semigroup](orchestrators :Seq[O], poll :(O)=>Future[T]) :Future[T] = 
 (Future traverse orchestrators)(poll(_)).map(_.reduce(_ |+| _))

输出

scala> pollAll(List(1, 2, 3, 4), (i: Int) => Future.successful(i)).foreach(println)

scala> 10

scala> pollAll2(List(1, 2, 3, 4), (i: Int) => Future.successful(i)).foreach(println)

scala> 10

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-21
    • 2015-11-28
    • 2020-02-11
    • 2021-08-25
    • 2011-08-29
    • 2022-11-13
    • 2020-10-12
    相关资源
    最近更新 更多