【问题标题】:Typeclass instances for unnamed types in ScalaScala 中未命名类型的类型类实例
【发布时间】:2013-06-30 17:36:33
【问题描述】:

如何在 Scala 中编码以下约束(伪代码)?

def foo(x: T forSome { type T has a Numeric[T] instance in scope }) = {
  val n= implicitly[...] // obtain the Numeric instance for x
  n.negate(x) // and use it with x
}

简而言之:我的输入参数需要一个类型类实例,但我不关心参数的类型,我只需要获取实例并将其用于我的参数。

它不一定是存在类型,但我需要避免def的签名中的类型参数。

编辑:只是为了澄清这些情况下的标准方法,即:

def foo[T: Numeric](x: T) = ...

对我不起作用,因为它需要在方法上添加类型参数。

谢谢。

【问题讨论】:

  • 为什么不能添加类型参数?
  • 因为它是方法中的第二个类型参数,我不想向用户公开。而且因为它是第二个,所以如果不推断第一个就无法推断,但在我的情况下,原则上不能推断出第一个。而且因为整个事情都是围绕宏发生的,所以我不能使用类似于:stackoverflow.com/a/10734268/1274237 的东西,因为宏不能被部分应用。
  • 没有第二个类型参数。扩展为def foo[T](x: T)(implicit num: Numeric[T]) = ...。据我所知,这是一种类型参数。
  • 我的意思是,在我的实际使用中,这将是第二个参数。

标签: scala typeclass


【解决方案1】:

我设法让它像这样工作:

implicit class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T])

def foo(iwn: InstanceWithNumeric[_]) {
  def genFoo[T](iwn: InstanceWithNumeric[T]) {
    println(iwn.n.negate(iwn.inst))
  }
  genFoo(iwn)
}

现在:

scala> foo(1)
-1

scala> foo(1.2)
-1.2

不是最漂亮的,但似乎有效。

编辑:您可以避免像这样定义内部函数:

implicit class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T]) {
  def negate = n.negate(inst)
}

另外,如果你想隐式转换为InstanceWithNumeric 全局可见,你可以这样做:

class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T])
object InstanceWithNumeric {
  implicit def apply[T: Numeric](inst: T) =
    new InstanceWithNumeric(inst)
}

如果您想了解其工作原理,请阅读所谓的隐式作用域this question 似乎包含很好的解释)。

【讨论】:

  • 虽然我不得不更严格地要求我,但你让我走上了正确的轨道,现在它可以工作了。非常感谢!
【解决方案2】:

不太清楚你在尝试什么,因为一旦你调用implicitly,你似乎需要一个类型。以下内容对您有用吗?

def foo(implicit x: Numeric[_]) {
   //code goes here.
}

【讨论】:

  • 我确实有一个实际的用例,虽然详细说明有点累。我确实需要参数和类型类实例的组合,我只是不关心类型参数,它们应该只兼容。所以你的解决方案对我不起作用,无论如何谢谢。
  • 所以我得到一个-1,因为你详细说明它很烦人,你仍然必须使用类型参数?
  • 我没有给你投反对票,只是为了补偿不公平,我给你投赞成票。很抱歉造成误解。
  • 没问题,我也很抱歉认为是你。谢谢ncreep。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
  • 2013-01-23
  • 2014-05-31
  • 2022-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多