Is there a nicer way of lifting a PartialFunction in Scala?

梦想的初衷 提交于 2019-12-10 18:29:42

问题


I occasionally come across the following pattern, where I essentially have a PartialFunction[SomeType,AnotherType], and want to treat it as a Function[SomeType,Option[AnotherType], eg:

def f(s:SomeType):Option[AnotherType] = s match {
  case s1:SubType1 => Some(AnotherType(s1.whatever))
  case s2:SubType2 => Some(AnotherType(s2.whatever))
  case _ => None
}

Is there a way to write the above function in a way that avoids the default case and wrapping the result in Some where it's defined? The best I've come up with so far is this:

def f(s:SomeType):Option[AnotherType] = pf.lift(s)
def pf:PartialFunction[SomeType,AnotherType] = {
  case s1:SubType1 => AnotherType(s1.whatever)
  case s2:SubType2 => AnotherType(s2.whatever)
}

Is there a way to do it without defining an intermediate function? I've already tried various things along the lines of the following, but haven't got anything to compile yet:

def f:Function[SomeType,Option[AnotherType]] = {
  case s1:SubType1 => AnotherType(s1.whatever)
  case s2:SubType2 => AnotherType(s2.whatever)
}.lift

回答1:


condOpt in object scala.PartialFunction. From the scaladoc:

def onlyInt(v: Any): Option[Int] = condOpt(v) { case x: Int => x }



回答2:


Not so much an answer, as an explanation of why huynhjl's answer is correct...

Part of your confusion is that you're trying to def a partial function. All this does is to create a method that returns a PartialFunction object, when you may as well create the thing directly:

val pf: PartialFunction[SomeType,AnotherType] = {
  case s1:SubType1 => AnotherType(s1.whatever)
  case s2:SubType2 => AnotherType(s2.whatever)
}

Though I personally prefer to use type ascription:

val pf = {
  case s1:SubType1 => AnotherType(s1.whatever)
  case s2:SubType2 => AnotherType(s2.whatever)
} : PartialFunction[SomeType,AnotherType]

Either way, you have to specify what the input type is, so you have to give the exact signature of the PartialFunction. I know it feels like it should be possible to to infer this but, alas, that is sadly not the case!

Using the ascribed version, you can then define and lift all in the same place:

val pf = ({
  case s1:SubType1 => AnotherType(s1.whatever)
  case s2:SubType2 => AnotherType(s2.whatever)
} : PartialFunction[SomeType,AnotherType]).lift

PartialFunction.condOpt is the better solution though, as it allows the inferencer to do most of this work for you, leaving much cleaner code :)



来源:https://stackoverflow.com/questions/4721391/is-there-a-nicer-way-of-lifting-a-partialfunction-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!