簡體   English   中英

概括 Int -> Int, Int-> String, String -> String, String -> Int

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM