【发布时间】:2016-12-07 10:27:12
【问题描述】:
我正在寻找一种优雅的方式来链接派生自公共基类型的部分函数。这个想法是每个部分函数都处理一个类型,因此它们可以很容易地组合成不同的类型,并且如果链接的部分函数未定义,则它们具有共同的包罗万象:
trait Message
trait SysMessage extends Message
trait UserMessage extends Message
case class TextSysMessage(m: String) extends SysMessage
case class TextUserMessage(m: String) extends UserMessage
class Test {
type MessagePF = scala.PartialFunction[Message, String]
type SysMessagePF = scala.PartialFunction[SysMessage, String]
type UserMessagePF = scala.PartialFunction[UserMessage, String]
def getSysMessage: SysMessagePF = {
case sm: TextSysMessage ⇒ s"System message: ${sm.m}"
}
def getUserMessage: UserMessagePF = {
case um: TextUserMessage ⇒ s"User message: ${um.m}"
}
def * : MessagePF = {
case m ⇒ s"Unknown message: $m"
}
// Chained partials fails because `m` is a SysMessage with UserMessage
def handler(m: Message): String = (getSysMessage orElse getUserMessage orElse *)(m)
}
显然,这种方法无法编译。我可以通过这样的嵌套模式匹配来解决这个问题
def getSysMessage: MessagePF = {
case m: SysMessage ⇒ m match {
case sm: TextSysMessage ⇒ s"System message: ${sm.m}"
}
}
但后来我失去了处理所有未知消息的能力。有没有什么优雅的方法可以实现这个目标?
【问题讨论】:
-
为什么不用
Message定义每个PartialFunction作为输入类型? -
本质上是B计划......
-
但是你怎么能期望一个带有具体子类型的部分函数可以与任意
Message一起工作呢?def handler(m: Message): String = (getSysMessage)(m)之类的东西也不起作用。 -
没想到会这样。只是在寻找一种优雅的方式来实现类似的目标。
-
getSysMessage和getUserMessage的全部目的是尝试在具体类型上匹配一些Message。如果您决定此部分函数必须采用Message的具体子类型,那么您已经(静态地)知道它属于这种类型,这与这些方法存在的意义不符。
标签: scala