传递蕴涵 - 这在Scala中是可能的吗? [英] transitive implicits - is this possible in Scala?

查看:107
本文介绍了传递蕴涵 - 这在Scala中是可能的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有几个函数:

  func1:A => B 

func2:B => C

func3:C => D

我想以通用的方式编排现在需要的函数。



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

lang.org/files/archive/nightly/docs/library/index.html#scala.language%24rel =nofollow>语言特性文档,解释了为什么隐式转换必须在2.10中明确启用:


为什么控制它?隐含转换已知会导致许多陷阱
(如果过度使用。而且有过度使用它们的倾向,因为它们
看起来非常强大,而且它们的效果似乎很容易理解。
另外,在大多数情况下,使用隐式参数会导致比隐式转换更好的
设计。

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



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

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

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

现在我们可以写出:

 隐式对象doubleToString extends MyConverter [Double,String] {
def apply(d:Double)= d.toString
}

隐式对象intToDouble extends MyConverter [Int,Double] {
def apply(i:Int)= i.toDouble

$ def def convertToString [A](a:A)(隐式为:MyConverter [A,String])= as(a)

最后:

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

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



与隐式转换类似,这种方法也可能被滥用,但更容易监视哪些转换器在范围内,它们在何处应用等。


Let's say I have several functions:

func1 : A => B

func2:  B => C

func3:  C => D

I would like to orchestrate now functions when needed in a generic fashion.

let's say if i need a conversion from A to B I'd call func1. But when I need a conversion from A to D I would like to have a composition of those functions. Is such thing possible in a dynamic notion?

解决方案

From the Scala documentation for language features, explaining why implicit conversions have to be explicitly enabled in 2.10:

Why control it? Implicit conversions are known to cause many pitfalls if over-used. And there is a tendency to over-use them because they look very powerful and their effects seem to be easy to understand. Also, in most situations using implicit parameters leads to a better design than implicit conversions.

User-defined implicit conversions are almost always a bad idea, and making them transitive would be much, much worse.

You can, however, use type classes to get a similar effect in a much safer, more controlled way. For example, suppose we have the following:

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)) }

Now we can write:

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)

And finally:

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

We've never explicitly defined a converter from integers to strings, but the compiler is able to use our composeMyConverters method to construct one when it's needed.

Like implicit conversions, this approach can also be abused, but it's much easier to keep tabs on what converters are in scope, where they're being applied, etc.

这篇关于传递蕴涵 - 这在Scala中是可能的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆