改进模式匹配代码



假设以下数据结构。

sealed abstract class Formula {...}
//... some other case classes
sealed abstract class BinaryConnective(f0: Formula, f1: Formula) extends Formula {
  def getf0 = f0
  def getf1 = f1
}
object BinaryConnective {
  def unapply(bc : BinaryConnective) = Some((bc.getf0, bc.getf1))
}
final case class Conjunction(f0: Formula, f1: Formula) extends BinaryConnective(f0,f1)
final case class Disjunction(f0: Formula, f1: Formula) extends BinaryConnective(f0,f1)
final case class Implication(f0: Formula, f1: Formula) extends BinaryConnective(f0,f1)
final case class Equivalence(f0: Formula, f1: Formula) extends BinaryConnective(f0,f1)

我现在编写了一个具有大量模式匹配的函数:

getCondition的返回类型是Formula => Option[HashMap[Variable, Formula]]

formula match {
//.. irrelevant cases not shown
case Conjunction(f0, f1) => (g : Formula) => {
    g match {
      case conj @ Conjunction(g0, g1) => {
        getCondition(f0)(conj.f0) match {
          case Some(map0) => {
            getCondition(f1)(conj.f1) match {
             case Some(map1) if map0.forall{case (key, value) => map1.get(key).map(_ == value).getOrElse(true)} => {
               Some(map0 ++ map1)
             }
             case _ => None
            }
          }
          case None => None
        }
      }
      case _ => None
    }
  }
}

现在回答我的问题。

1)有没有更好的方法来表达这个代码?很多比赛正在进行中。

编辑1:我想不出一种好看的方式来使用mapfilter等东西,但它似乎非常紧凑,易于理解。我还注意到conj @根本不必要,这也使它更简单一些。

case Conjunction(f0, f1) => (g: Formula) => g match {
  case Conjunction(g0, g1) => for {
      map0 <- getCondition(f0)(g0)
      map1 <- getCondition(f1)(g1)
      if map0.forall {case (key, value) => map1.get(key).map(_ ==  value).getOrElse(true)}
    } yield map0 ++ map1
  case _ => None
}

2)这是Conjunction的匹配。我将不得不重复它DisjunctionImplicationEquivalenceg必须与formula属于同一类。唯一会改变的是 case conj @ Conjunction(g0, g1) .我必须将其调整为case disj @ Disjunction(g0, g1) formula是否是析取等......有没有办法对所有情况进行组合?

Option应该提供许多有用的函数来简化您的代码。

例如,当您编写类似以下内容时:

o match {
  case Some(e) => Some(transform(e))
  case _ => None
}

你可以打电话给mapo.map(transform)

我还邀请您查看包括条件在内的情况的filter函数。

编辑:@om-nom-nom的伟大建议:也可以使用理解(它们实际上是依赖于mapflatMapfilter等的糖):

for{
  e <- o
} yield transform(e)

最新更新