[英]generalize Int -> Int, Int-> String, String -> String, String -> Int
我有 4 种方法,一种逻辑和 4 种可能的类型映射:
def convertStringToString(in: String): String = ???
def convertIntToString(in: Int): String = ???
def convertIntToInt(in: Int): Int = ???
def convertStringToInt(in: String): Int = ???
我想概括输入和 output 类型并用一种方法编写逻辑。 试图通用化输入参数:
def convertToInt[IN](in: IN): Int = in match {
case x: String if x.forall(_.isDigit) => x.toInt
case y: Int => y
case _ => 0
}
def convertToString[IN](in: IN): String = convertToInt[IN](in).toString
你能帮我概括一下吗:
def convertToInt[IN, OUT](in: IN): OUT = ???
如果你真的想要,你可以有一些基于类型类的东西:
def convert[I, O](in: I)(implicit c: ConversionRule[I, O]): O = {
if (c.isConvertible(in)) c.convert(in)
else c.zero
}
trait ConversionRule[I, O] {
def isConvertible(in: I): Boolean
def convert(in: I): O
def zero: O // Could possibly derive the zero from, e.g., a cats Monoid instance where such exists
}
眼尖的人可能会注意到isConvertible
/ convert
方法与PartialFunction[I, O]
的isDefinedAt
/ apply
的合同相匹配,所以不妨只使用PartialFunction
(并用isDefinedAt
/ apply
重写convert
)
trait ConversionRule[I, O] extends PartialFunction[I, O] {
def zero: O
}
zero
可以根据PartialFunction.applyOrElse
来实现,但是对于zero
为常数的情况(即保留引用透明度的情况),这要快得多。
可以定义智能构造函数:
object ConversionRule {
def apply[I, O](zeroValue: O)(pf: PartialFunction[I, O]): ConversionRule[I, O] =
new ConversionRule[I, O] {
override def apply(i: I): O = pf(i)
override def isDefinedAt(i: I): Boolean = pf.isDefinedAt(i)
val zero: O = zeroValue
}
def totalConversion[I, O](f: I => O): ConversionRule[I, O] =
new ConversionRule[I, O] {
override def apply(i: I) = f(i)
override def isDefinedAt(i: I) = true
override def zero: O = throw new AssertionError("Should not call since conversion is defined")
}
// Might want to put this in a `LowPriorityImplicits` trait which this object extends
implicit def identityConversion[I]: ConversionRule[I, I] =
totalConversion(identity)
}
identityConversion
意味着自动生成一个convertIntToInt
。
convertStringToInt
然后可以定义为
implicit val stringToIntConversion = ConversionRule[String, Int](0) {
case x if x.forAll(_.isDigit) => x.toInt
}
可以定义一个基于toString
的转换(基本上是为 alleycats 提出的非法Show
):
implicit def genericToString[I]: ConversionRule[I, String] =
ConversionRule.totalConversionRule(_.toString)
然后应该可以定义一个stringViaInt
ConversionRule
派生,如:
implicit def stringViaInt[I, O](implicit toInt: ConversionRule[I, Int]): ConversionRule[I, String] =
convert(convert(in)(toInt))
它提供的唯一真正有用的东西是选择使用隐式转换。 这是否足以证明是合理的? 耸耸肩
(免责声明:只有我脑海中的 scala 编译器试图编译这个)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.