如何使用部分函数进行类型推断

时间:2013-07-12 16:55:04

标签: scala type-inference function-composition

我想定义一个使用partial函数处理消息的类的层次结构。每个类都应该将它无法处理的消息推迟到它的超类。像这样:

type Respond = PartialFunction[String, String]

abstract class HandlesNothing {
  def respond: Respond = Map.empty // the empty response. Handles nothing
}

class HandlesA extends HandlesNothing {
  override def respond = { case "a" => "The letter A" } orElse super.respond
}

class HandlesAAndB extends HandlesA {
  override def respond = { case "b" => "The letter B" } orElse super.respond
}

你明白了。但是当我尝试这个时,我得到以下错误

<console>:21: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
         override def respond = { case "b" => "The letter B" } orElse super.respond
                                ^

当我明确地给出{...}块的类型时,它可以工作:

class HandlesAAndB extends HandlesA {
  override def respond = ({ case "b" => "The letter B" }:Respond) orElse super.respond
}

有没有办法实现这一点而无需明确指定部分功能块的类型?

2 个答案:

答案 0 :(得分:2)

问题是orElse左侧的类型由于右侧存在而被方法的返回类型指定不充分。 (另外,LHS不是语法必然是部分函数;它可能是一个未完全指定的Function1。)因为即使在概念上编译器也不能在没有一点额外帮助的情况下真正做正确的事情,你'我必须做点什么。

所以唯一的问题是,是否有比: Respond更好的方式来指示左侧的类型。事实证明答案是也许

implicit class Resp(val underlying: Respond) extends AnyVal {
  def or(r: Respond) = underlying orElse r
}

abstract class A { def respond: Respond = Map.empty }
class B extends A {
  override def respond = Resp{ case "A" => "The letter A" } or super.respond
}

由于使用了隐式值类,因此基本上没有这样做的开销。成本是你有一个自定义迷你DSL而不是香草Scala库调用。

答案 1 :(得分:1)

你能做到:

abstract class HandlesNothing {
  def respond: Respond = Map.empty // the empty response. Handles nothing
  protected def c(supPf: Respond)(pf: Respond) = pf orElse supPf
}

class HandlesA extends HandlesNothing {
  override def respond = c(super.respond) { case "a" => "The letter A" }
}

这无疑是丑陋的,但可以节省你的打字。

在探索过程中发现有趣的细节:无法绑定super的{​​{1}}。那会非常酷。