【问题标题】:transitive implicits - is this possible in Scala?传递隐式 - 这在 Scala 中可能吗?
【发布时间】:2013-10-20 13:14:31
【问题描述】:

假设我有几个函数:

func1 : A => B

func2:  B => C

func3:  C => D

我想在需要时以通用方式编排 now 函数。

假设我需要从A 转换为B,我会打电话给func1。 但是当我需要从AD 的转换时,我想要这些函数的组合。在动态概念中这样的事情可能吗?

【问题讨论】:

  • 考虑到隐式已经杀死了编译时间并降低了项目的整体可读性,从而降低了工作时的整体生产力,你想要的听起来是一个非常糟糕的主意。

标签: function scala implicit


【解决方案1】:

来自 Scala documentation for language features,解释了为什么必须在 2.10 中显式启用隐式转换:

为什么要控制它?众所周知,隐式转换会导致许多陷阱 如果过度使用。并且有过度使用它们的趋势,因为它们 看起来很强大,它们的效果似乎很容易理解。 此外,在大多数情况下,使用隐式参数会导致更好的 设计而不是隐式转换。

用户定义的隐式转换几乎总是一个坏主意,并且使它们具有传递性会更糟。

但是,您可以使用类型类以更安全、更可控的方式获得类似的效果。例如,假设我们有以下内容:

trait MyConverter[A, B] { def apply(a: A): B }

implicit def composeMyConverters[A, B, C](implicit
  ab: MyConverter[A, B],
  bc: MyConverter[B, C]
) = new MyConverter[A, C] { def apply(a: A) = bc(ab(a)) }

现在我们可以写了:

implicit object doubleToString extends MyConverter[Double, String] {
  def apply(d: Double) = d.toString
}

implicit object intToDouble extends MyConverter[Int, Double] {
  def apply(i: Int) = i.toDouble
}

def convertToString[A](a: A)(implicit as: MyConverter[A, String]) = as(a)

最后:

scala> convertToString(13: Int)
res0: String = 13.0

我们从未明确定义过从整数到字符串的转换器,但编译器能够在需要时使用我们的composeMyConverters 方法构造一个。

与隐式转换一样,这种方法也可能被滥用,但更容易关注范围内的转换器、应用它们的位置等。

【讨论】:

  • 我喜欢你的 Travis 方法,但实际上你的链接隐含使它们具有传递性?
  • 是的,但是链接是自动发生的,而且这些不是隐式转换——它们是编译器为满足隐式参数而产生的类型类实例。
  • 您能否详细说明这种差异以及为什么它很重要?
  • 整个标准库都有隐式转换,任何人都可以定义更多,而且可以应用到你意想不到的地方。在我的示例中,您已经定义了类型类,因此您确切知道哪些实例可用,并且不会自动应用转换 - 您必须使用我的 convertToString 方法中看到的隐式参数方法。
  • 嘿 Travis,我们只是尝试为更长的链(A -> B -> C -> D)做这个,我们得到了不同的推导,这对我们来说很有意义,因为函数组合是关联的,因此不同的分组会导致多个实例。我怀疑我们可以教 scalac 关联性,所以我想知道是否有办法避免分歧。希望答案不是宏。
猜你喜欢
  • 2014-04-28
  • 1970-01-01
  • 2018-06-03
  • 1970-01-01
  • 1970-01-01
  • 2011-10-09
  • 1970-01-01
  • 2014-10-09
  • 1970-01-01
相关资源
最近更新 更多