【问题标题】:Is there a more elegant way to write this using Scalaz?有没有更优雅的方式来使用 Scalaz 编写这个?
【发布时间】:2012-08-31 22:02:08
【问题描述】:

下面的代码有效,但选项 b 上的模式匹配看起来并不优雅。 有没有办法在保持相同语义的同时避免它?

object A {
  def apply(b: B): ValidationNEL[String, A] = ...
}

case class C(i: Int, a: Option[A])

object C {
  def apply(i: Int, b: Option[B]): ValidationNEL[String, C] = b match {
    case None => Success(C(i, None))
    case Some(sb) => A(sb).map(bb => C(i, Some(bb)))
  }     
}

【问题讨论】:

  • “优雅”是主观的。如果您对模式匹配感到不舒服,请直说,但标记为“优雅”或不分散注意力。如果您只是在寻找表达相同结构的替代方法,请直说
  • @AndreasScheinert:在某种程度上,优雅是由社区定义的,在经验丰富的 Scala 开发人员中,Option 上的模式匹配肯定不受欢迎。
  • 在这种特殊情况下,可能有大多数人有这种偏好。我仍然不喜欢将“优雅”一词与“风格”结合使用,但可能只有我一个人 ;)

标签: scala scalaz


【解决方案1】:

使用 scalaz,您可以折叠 Option

b fold ( sb => A(sb) map (bb => C(i, some(bb))), C(i, none).success)

可能有一种方法可以简化 sb => A(sb) map (bb => C(i, some(bb))) 使用 pointfree 样式,但这在 scala 中通常很难看:

设置

scala> :paste
// Entering paste mode (ctrl-D to finish)

object A {
  def apply(b: B): ValidationNEL[String, A] = sys.error("")
}
case class A()
case class B()
case class C(i: Int, a: Option[A])

// Exiting paste mode, now interpreting.

defined module A
defined class A
defined class B
defined class C

第一个实现

scala> def apply(i: Int, b: Option[B]): ValidationNEL[String, C] =
     | b fold ( sb => A(sb) map (bb => C(i, some(bb))), C(i, none).success)
apply: (i: Int, b: Option[B])scalaz.Scalaz.ValidationNEL[String,C]

第二个实现

如果你声明一等函数,你就有更好的组合机会。例如:

object A { val fromB: B => ValidationNEL[String, A] = _ => sys.error("") }
object C { val fromA: Int => A => C = i => a => C(i, some(a)) }

defined module A
defined module C

然后

scala> def apply(i: Int, b: Option[B]): ValidationNEL[String, C] =
     | b fold (A.fromB andThen (_ map C.fromA(i)), C(i, none).success)
apply: (i: Int, b: Option[B])scalaz.Scalaz.ValidationNEL[String,C]

【讨论】:

    【解决方案2】:

    你甚至不需要 scalaz 特定的东西来简化这个,只需使用Option.map

    b.map { sb => /* will only be called if b is Some[A] */ }.getOrElse { /* will only be called if b is None */ }
    

    我不能给你确切的解决方案,因为你发布的代码不完整。 case class C 中的 A 不在范围内。这应该是一个类型参数,还是有一个属于object Aclass A

    【讨论】:

    • ValidationNEL 是一个验证
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多