Scala 安全链接隐式转换

Scala 安全链接隐式转换,scala,implicit-conversion,implicits,Scala,Implicit Conversion,Implicits,可以执行此操作以获得到链的隐式转换: package language object chainedImplicits { implicit def chainImplicits[A, B, C](a: A)(implicit conv1: A => B, conv2: B => C): C = conv2(conv1(a)) } 但这显然不安全 不过,我看不出这个版本有什么问题: package language package chainedImplicits {

可以执行此操作以获得到链的隐式转换:

package language

object chainedImplicits {
  implicit def chainImplicits[A, B, C](a: A)(implicit conv1: A => B, conv2: B => C): C = conv2(conv1(a))
}
但这显然不安全

不过,我看不出这个版本有什么问题:

package language

package chainedImplicits {

  final class Chained[A, B] private[chainedImplicits] (val f: A => B)

  trait Low { this: `package`.type =>
    implicit def startChaining(implicit conv: A => B): Chained[A, B] = new Chained[A, B](conv)
    implicit def chainImplicits[A, B, C](implicit conv1: Chained[A, B], conv2: B => C): Chained[B, C] = new Chained(conv1.f andThen conv2)
  }

}

package object chainedImplicits extends Low {
  implicit def endChain[A, B](a: A)(implicit conv: Chained[A, B]): B = conv.f(a)
}

这里有什么问题吗?

首先,我不能让你的第一个“显然不安全”的例子做任何事情:

import language.implicitConversions

object Test {
  implicit def chain[A, B, C](a: A)(implicit ab: A => B, bc: B => C): C = bc(ab(a))

  case class X()
  case class Y()
  case class Z()

  implicit def xy(x: X) = Y()
  implicit def yz(y: Y) = Z()

  val z: Z = X()
}

接下来,第二个示例中明显的“陷阱”是它没有编译。你真的试过了吗?无论如何,在“修复”它之后,它仍然不能满足您的要求:

import language.implicitConversions

class Convert[A, B](val convert: A => B) extends AnyVal
trait Convert0 {
  implicit def convert[A, B](implicit ab: A => B): Convert[A, B] = new Convert(ab)
  implicit def convert[A, B, C](implicit ab: Convert[A, B], bc: B => C): Convert[A, C] = new Convert(ab.convert andThen bc)
}
object Convert extends Convert0 {
  implicit def convert[A, B](a: A)(implicit convert: Convert[A, B]): B = convert.convert(a)
}

object Test {
  case class X()
  case class Y()
  case class Z()

  implicit def xy(x: X) = Y()
  implicit def yz(y: Y) = Z()

  val z: Z = X()
}
这会产生相同的类型不匹配错误。据我所知,如果您希望隐式转换为chain,则必须明确:

import language.implicitConversions

object test {
  case class X()
  case class Y()
  case class Z()

  // anything convertible to X is convertible to Y
  implicit def xy[A <% X](x: A) = Y()

  // anything convertible to Y is convertible to Z
  implicit def yz[B <% Y](y: B) = Z()

  val z: Z = X()
}
import language.implicitConversions
对象测试{
案例类别X()
案例类别Y()
案例类别Z()
//任何可以转换为X的东西都可以转换为Y

隐式定义xy[A为什么代码的第一个代码块显然不安全?Scala能否通过实例化具有相同具体类型的
A
C
来创建无限隐式链?@mhs否,因为Scala只有在代码不进行类型检查的情况下才会调用隐式转换。第一个隐式链的危险在于CIT可能不是唯一的模最终签名。
import language.implicitConversions

object test {
  case class X()
  case class Y()
  case class Z()

  // anything convertible to X is convertible to Y
  implicit def xy[A <% X](x: A) = Y()

  // anything convertible to Y is convertible to Z
  implicit def yz[B <% Y](y: B) = Z()

  val z: Z = X()
}