从A隐式转换为Some(a)

时间:2018-12-30 03:05:33

标签: scala functional-programming

出于好奇,我想知道是否有可能做类似的事情:

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 :(得分:3)

可能,是的

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)
  }
}

您应该这样做吗? 。为什么?因为具有如此广泛范围的隐式是危险的。首先,当您实际需要范围内的相关隐式变量时,它们可能导致歧义。其次,当某人阅读此内容时,他们将需要查看此转换发生的位置以及原因。第三,这可能导致细微的错误。

相反,无论您是从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)
  }
}

答案 1 :(得分:2)

我最喜欢的解决方案是:

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仅用于 作为默认参数,因此隐式转换是无害的。

答案 2 :(得分:1)

根据评论中的Luis Miguel Mejía Suárez的建议,您可以像这样使用隐式的猫:

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
}