Неявное преобразование из А в Некоторые (а) - PullRequest
0 голосов
/ 30 декабря 2018

из любопытства, мне было интересно, можно ли было сделать что-то вроде:

def myMethod(
  a: Option[A] = None,
  b: Option[B] = None, 
  ...
  z: Option[Z] = None
): Something = {
  ...
}

То, что я хочу, - не называть это так:

myMethod(
  b = Some(newB),
  m = Some(newM)
)

но вместо этого можно просто сделать myMethod(b = newB, m = newM) без необходимости всегда конвертировать A в Some(a).

Возможно ли это?

Ответы [ 3 ]

0 голосов
/ 30 декабря 2018

как Луис Мигель Мехия Суарес предложил в комментариях, вы можете использовать неявных кошек, как это:

import cats.syntax.option.catsSyntaxOptionId
//import cats.implicits._ //or you could import everything

object Example1 {
  def foo(i: Option[Int]): Boolean = ???

  def myFunction(a: Int, b: Int): Int =
    if (foo(a.some)) 0 else b //a.some is from cats implicit
}

То, что вы не хотите делать, это расширить свою функцию допринимать больше значений только для того, чтобы тип соответствовал какой-либо внутренней реализации.

object Example2 {
  def foo(i: Option[Int]): Boolean = ???

  // don't take an option if you don't expect None
  def myFunction(a: Option[Int], b: Int): Int =
    if (foo(a)) 0 else b
}

Если вы не берете None в качестве параметра, то вполне нормально преобразовать значения явно, когда вам необходимо:

object Example3 {
  def foo(i: Option[Int]): Boolean = ???

  def myFunction(a: Int, b: Int): Int =
    if (foo(Some(a))) 0 else b
}
0 голосов
/ 02 января 2019

Мое любимое решение таково:

class Opt[A](val value: Option[A]) extends AnyVal
object Opt {
   implicit def fromA[A](x: A): Opt[A] = new Opt(Some(x))
   implicit def toOption[A](x: Opt[A]): Option[A] = x.value
   def N[A]: Opt[A] = new Opt(None) 
}

def myMethod(
  a: Opt[A] = Opt.N,
  ...
  z: Opt[Z] = Opt.N
): Something = ...

Поскольку Opt используется только для параметров по умолчанию, неявные преобразования безвредны.

0 голосов
/ 30 декабря 2018

Возможно, да:

object Test {
  implicit def anythingToOption[A](a: A): Option[A] = Option(a)
  def foo(something: Option[Int]): Unit = ???

  def main(args: Array[String]): Unit = {
    foo(1)
  }
}

Должны ли вы сделать это? NO .Зачем?Потому что последствия с такими широкими рамками опасны.С одной стороны, они могут привести к неоднозначности, когда вам действительно нужен соответствующий неявный по объему.Во-вторых, когда кто-то читает это, ему нужно увидеть, где происходит это преобразование и почему.В-третьих, это может привести к незначительным ошибкам.

Вместо этого вы можете использовать методы расширения, независимо от того, получаете вы их из библиотеки Cats или пишете сами:

object Test {
  implicit class OptionOps[A](val a: A) extends AnyVal {
    def toOption: Option[A] = Option(a)
    def some: Option[A] = Some(a)
  }

  def foo(something: Option[Int]): Unit = ???
  def main(args: Array[String]): Unit = {
    foo(1.toOption)
    foo(1.some)
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...