Scala不能处理非显式类型的闭包用于冒号函数

4

基本上我想要编写一个可以这样写的函数:

{ println(_) } =: thing

我希望它实际执行的是 thing.=:(println(_))。为了论证这一点,假设=:有以下实现:

def =:(block : Int => Any) {
    block(5)
}

我尝试按照上述方式调用,但出现了以下结果:

<console>:10: error: type mismatch;
   found   : Unit
   required: Int => Any
             println(_) =: thing

我接着试着这样做:

thing.=:(println(_))

这样我就可以在终端上得到一个漂亮的5。然后我尝试了这个:

{ value => println(value) } =: thing

这次再次失败并告诉我有一个“缺少参数类型”。我猜测这是因为Scala在这种情况下首先尝试解析/编译函数参数,并且不像使用点运算符调用时那样猜测类型(这里完全是我的猜测)。

有人可以详细说明这里的问题,同时也可以建议实现接近原始目标的最佳方法吗?

P.S. 对于标题抱歉,我会在更好地理解问题后重命名它。

2个回答

6

类型推断是从左到右进行的,即使符号方法名采用#:形式最终从右到左工作。如果您实际上只有一种类型,可以使用帮助器方法:

def let(fi: Int => Any) = fi
case class Thing(i: Int) {
  def =:(f: Int => Any) = f(i)
}

scala> let(_+2) =: Thing(5)
res4: Any = 7

但是,如果你有许多可能的类型签名,这并不是完全令人满意的解决方案,因为你必须将左侧的辅助方法名称与右侧所需的类型匹配。


有没有办法使用隐式函数来实现这个?我猜想不行,因为Scala不会寻找一个隐式函数,而是会认为类型不匹配。另外,如果您知道原因,能否在回答中解释一下为什么类型推断不能从右到左工作于这些函数上。 - seadowg
@Oetzi - 从右到左让类型推断器工作会更费力。原则上它是可以完成的,只是现有实现的限制。 - Rex Kerr

1

那么为什么不添加参数类型:

{ value:Int => println(value) } =: thing

我自己不是Scala专家,因此无法提供有关推理器可以推理什么和不能推理什么的更深入解释。


这确实可行,但我正在编写一种DSL,其中每个闭包都具有相同的输入类型,因此这将非常单调。 - seadowg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接