Цепочка Scala подразумевает преобразования для Option [T] - PullRequest
0 голосов
/ 25 апреля 2018

Я пытаюсь сделать цепочку неявных преобразований из Symbol -> A -> Option [A]. Но не удается заставить его работать с обычным преобразованием Option, например:

implicit def toInt(n: Symbol): Int = n.toString.length
implicit def symbolToString(n: Symbol): String = n.toString
implicit def toOptStr[T](b: T)(implicit fn: T ⇒ String): Option[String] = Option(b)
implicit def toOptInt[T](b: T)(implicit fn: T ⇒ Int): Option[Int] = Option(b)

И это прекрасно работает:

val c: Option[Int] = 'a25768xffff // returns Some(12)
val d: Option[String] = 'a2699 // returns Some('a2699) 

Но я должен явно определить toOptStr[T](b: T): Option[String] и toOptInt[T](b: T)(implicit fn: T ⇒ Int): Option[Int]

Вместо этого я хочу добиться только одного общего преобразования toOptT, которое можно преобразовать в Option[T] при условии неявного преобразования из T=>V, что-то вроде следующего:

implicit def toInt(n: Symbol): Int = n.toString.length
implicit def symbolToString(n: Symbol): String = n.toString
implicit def toOptT[T,V](b: T)(implicit fn: T ⇒ V): Option[V] = Option(fn(b))

val c: Option[Int] = 'a25768xffff 
val d: Option[String] = 'a2699 

К сожалению, 2 последние строки дают ошибку компиляции:

Error:(34, 93) type mismatch;
   found   : Symbol
   required: Option[Int]
Error:(35, 96) type mismatch;
   found   : Symbol
   required: Option[String]

Любая помощь очень ценится.

Пробовал на Scala 12.2.5. Есть несколько связанный вопрос: Цепное неявное преобразование коллекции , цепочка подразумевает детали. FAQ: https://docs.scala -lang.org / tutorials / FAQ / chaining-implicits.html

1 Ответ

0 голосов
/ 25 апреля 2018

Не удалось заставить его работать на 2.12.5.

Вот один из возможных способов:

implicit val toInt: Symbol => Int = _.toString.length
implicit val symbolToString: Symbol => String = _.toString
implicit class ToOptOps[S](s: S) {
  def toOpt[T](implicit c: S => T): Option[T] = Option(c(s))
}

val c = 'a25768xffff.toOpt[Int]
val d = 'a2699.toOpt[String]

Я бы посоветовал вам использовать только классы типов в сочетании с неявными классами для"pimp-the-interface" (добавление новых методов, в данном случае toOpt).Здесь нужно фактически заменить implicit c: S => T на соответствующий класс типов, чтобы избежать нежелательных коллизий.Сочетание классов типов с «сутенерством» оказалось надежным.В противоположность этому неявные преобразования кажутся просто злом.

...