带有泛型的隐式scala类

问题描述 投票:0回答:1

我有此代码:

object Peek {
    implicit def traversableToPeek[A](underlying: Traversable[A]) = new Peek(underlying)
}
class Peek[A](underlying: Traversable[A]) {

    /**
     * Java-style peek method
     */
    def peek(func: A => Unit): Traversable[A] = {
        underlying.foreach(func)
        underlying
    }
}

同时让我写List(1,2,3).peek(println).map(_+1).peek(println)这样的东西,先打印1,2,3,然后再打印2,3,4(在import Peek._之后)

但是,该表达式的编译时值为Traversable[Int]。这意味着尽管此代码可以编译:

val l = List(1,2,3)
val l2 = 4 :: l

此代码不:

val l = List(1,2,3).peek(println)
val l2 = 4 :: l

因为未在::上定义Traversable。窥视的目的是仅允许副作用操作,而无需像l.map(e => println(e); e)

这样的难看结构

我尝试添加第二个通用参数T <: TraversableT[A] <: Traversable[A],但无法以隐式转换起作用的方式对其进行编译。

我认为应该可以,但是我对Scala不够熟悉,无法正确使用语法。

scala generics implicit
1个回答
2
投票

第二个通用参数是正确的方法:

implicit class Peek[C[X] <: Traversable[X], A](underlying: C[A]) {
  def peek(func: A => Unit): C[A] = {
    underlying.foreach(func)
    underlying
  }
}

(在Scala 2.13中,将不推荐使用的Traversable替换为Iterable)。

如果您的类型扩展了Traversable[Something]本身不是通用的,则上面的方法将无效,但是

implicit class Peek[C <: Traversable[A], A](underlying: C with Traversable[A]) {
  def peek(func: A => Unit): C = {
    underlying.foreach(func)
    underlying
  }
}

应该。

© www.soinside.com 2019 - 2024. All rights reserved.