scala - 使用 scala 猫检查非空字段的组合
问题描述
在我的代码中,我有一个类来检查它是否有效我应该评估是否存在至少一个可能的字段组合(通过存在是指组合的每个字段都不应该为空)。例子:
case class Test( a: Option[String]
, b: Option[String]
, c: Option[String]
, d: Option[String]
, e: Option[Double]
, f: Option[Double])
要“有效”,必须至少存在以下字段组合之一(“a,b,c”,“a,d,e”,“a,f”)
我试图用 scala 猫库来做到这一点,但我有点迷路了。任何建议将不胜感激。
解决方案
如果你想验证它,你可以:
case class Test( a: Option[String]
, b: Option[String]
, c: Option[String]
, d: Option[String]
, e: Option[Double]
, f: Option[Double]) {
// "a,b,c","a,d,e","a,f"
def isValid = (a.isDefined && b.isDefined && c.isDefined) ||
(a.isDefined && d.isDefined && e.isDefined) ||
(a.isDefined && f.isDefined)
}
如果要确保仅在定义了一个字段时才能创建它,则必须使用智能构造函数
sealed abstract case class Test private ( a: Option[String]
, b: Option[String]
, c: Option[String]
, d: Option[String]
, e: Option[Double]
, f: Option[Double])
object Test {
def create( a: Option[String]
, b: Option[String]
, c: Option[String]
, d: Option[String]
, e: Option[Double]
, f: Option[Double]): Either[String, Test] =
if ((a.isDefined && b.isDefined && c.isDefined) ||
(a.isDefined && d.isDefined && e.isDefined) ||
(a.isDefined && f.isDefined))
Right(new Test(a, b, c, d, e, f) {})
else
Left("All arguments are empty")
}
或者使用 ADT 确保定义了一个字段:
sealed trait Test extends Product with Serializable
object Test {
final case class Case1( a: String
, b: String
, c: String
, d: Option[String]
, e: Option[Double]
, f: Option[Double]) extends Test
final case class Case2( a: String
, b: Option[String]
, c: Option[String]
, d: String
, e: String
, f: Option[Double]) extends Test
final case class Case3( a: String
, b: Option[String]
, c: Option[String]
, d: Option[String]
, e: Option[Double]
, f: Double) extends Test
}
你可以在这里使用 Cats ......但是为了什么?您没有将元组或选项集合组合成一个选项。你不换成F[Option[X]
或Option[F[X]
相反。没有副作用,映射,遍历,从嵌入在某些上下文中的较小对象构造新对象等。您可以尝试执行以下操作
implicit val booleanMonoid: Monoid[Boolean] = new Monoid[Boolean] {
def combine(a: Boolean, b: Boolean) = a && b
def empty = true
}
def isValid = List(a, b, c).foldMap(_.isDefined) ||
List(a, d, e).foldMap(_.isDefined) ||
List(a, f).foldMap(_.isDefined)
甚至可能
def isValid = (
(a, b, c).tupled.void orElse (a, d, e).tupled.void orElse (a, f).tupled.void
).isDefined
但这几乎没有比
def isValid = List(a, b, c).exists(_.isDefined) ||
List(a, d, e).exists(_.isDefined) ||
List(a, f).exists(_.isDefined)
可以在香草 Scala 中实现。我想你可以通过使用一些Ring
定义的符号来简单地Option[_]
使用*
和+
:
implicit val ring: Ring[Option[_]] = ... // yup, existential type here
def isValid = ((a * b * c) + (a * d * e) + (a * f)).isDefined
(这将需要typelevel algebra)但是仅在一个地方使用它我看不到收益。
推荐阅读
- android - Maps 解决了 arraylist 中的存储问题
- java - 如何在 android studio 中将 3 个 int rgb 值转换为一个 int 颜色值?
- ios - DFPBannerView 和 GADBannerView 有什么区别?
- javascript - 如何诊断/调试 nodejs/expressjs 的 500 内部服务器错误?
- python - 脚本不显示按钮
- google-api - Accessing google apis on behalf of google home user
- grails - 在 grails 3 应用程序中,什么是微调器,我需要 application.js 吗?
- python - 绘制参数变化的给定函数的热图
- java - 用按钮设置的倒数计时器
- json - 无法使用 read_json 读取 json 文件