对隐式对象或值中的参数类型进行抽象?

发布于 2024-10-15 02:28:43 字数 1086 浏览 3 评论 0原文

考虑隐式对象的这种应用

trait Splitter[A,B,C] {
   def split(list: List[C]):(List[A],List[B])
}

implicit object PairSplitter extends Splitter[Int, String, Pair[Int,String]] {
   override def split(list: List[Pair[Int,String]]):(List[Int],List[String]) =
     (list.collect{case (a,_) => a}, list.collect{case (_,b) => b})
}

implicit object EitherSplitter extends Splitter[Int, String, Either[Int,String]] {
   override def split(list: List[Either[Int,String]]):(List[Int],List[String]) =
     (list.collect{case Left(a) => a}, list.collect{case Right(b) => b})
}

def splitList[A,B,C](list:List[C])(implicit splitter:Splitter[A,B,C]):(List[A],List[B]) = splitter.split(list)

println(splitList(List((1,"one"),(2,"two"))).isInstanceOf[(List[Int],List[String])])
println(splitList(List[Either[Int,String]](Left(42),Right("two"))).isInstanceOf[(List[Int],List[String])])
//println(splitList(List(1,2,3,4))) //won't compile

它可以工作,但显然不是很有用。对于示例中的 Int 和 String 等具体类型编写此代码没有问题,但我认为无法编写抽象 A 和 B 的隐式对象或 val。

这可以完成吗?如何完成?如果不是,那么期望语言扩展具有这种能力是否合理?

Consider this application of implicit objects

trait Splitter[A,B,C] {
   def split(list: List[C]):(List[A],List[B])
}

implicit object PairSplitter extends Splitter[Int, String, Pair[Int,String]] {
   override def split(list: List[Pair[Int,String]]):(List[Int],List[String]) =
     (list.collect{case (a,_) => a}, list.collect{case (_,b) => b})
}

implicit object EitherSplitter extends Splitter[Int, String, Either[Int,String]] {
   override def split(list: List[Either[Int,String]]):(List[Int],List[String]) =
     (list.collect{case Left(a) => a}, list.collect{case Right(b) => b})
}

def splitList[A,B,C](list:List[C])(implicit splitter:Splitter[A,B,C]):(List[A],List[B]) = splitter.split(list)

println(splitList(List((1,"one"),(2,"two"))).isInstanceOf[(List[Int],List[String])])
println(splitList(List[Either[Int,String]](Left(42),Right("two"))).isInstanceOf[(List[Int],List[String])])
//println(splitList(List(1,2,3,4))) //won't compile

It works, but obviously isn't terrible useful. It's no problem to write this for concrete types like Int and String in the example, but I see no way to write an implicit object or val which abstracts over A and B.

Can this be done, and how? If not, is it reasonable to expect a language extension which has this ability?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧街凉风 2024-10-22 02:28:43

Scala 的值(即 val 和对象)是单态的,因此如果您坚持将隐式作为值,则没有直接的方法可以得到您想要的东西。

但是,如果它们不必是值,则有一个简单的替代方案:您可以使用可以多态的东西,隐式方法

implicit def pairSplitter[A, B] = new Splitter[A, B, Pair[A, B]] {
  override def split(list: List[Pair[A, B]]) : (List[A], List[B]) =
    (list.collect{case (a,_) => a}, list.collect{case (_,b) => b})
} 

REPL会话......

scala> splitList(List(("foo",2.0),("bar",3.0)))
res5: (List[java.lang.String], List[Double]) = (List(foo, bar),List(2.0, 3.0))

Scala's values (ie. vals and objects) are monomorphic, so there's no direct way of getting what you're after if you insist on the implicits being values.

But there's a straightforward alternative if they don't have to be values: you can use something which can be polymorphic, an implicit method,

implicit def pairSplitter[A, B] = new Splitter[A, B, Pair[A, B]] {
  override def split(list: List[Pair[A, B]]) : (List[A], List[B]) =
    (list.collect{case (a,_) => a}, list.collect{case (_,b) => b})
} 

REPL session ...

scala> splitList(List(("foo",2.0),("bar",3.0)))
res5: (List[java.lang.String], List[Double]) = (List(foo, bar),List(2.0, 3.0))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文