繁体   English   中英

如何在scala中使用泛型创建部分函数?

[英]How do I create a partial function with generics in scala?

我正在尝试为Scala编写性能测量库。 我的想法是透明地“标记”部分,以便可以收集执行时间。 不幸的是我无法按照我的意愿弯曲编译器。

一个公认的例子,说明了我的想法:

// generate a timing function
val myTimer = mkTimer('myTimer) 

// see how the timing function returns the right type depending on the
// type of the function it is passed to it
val act = actor {
    loop { 
        receive {

            case 'Int =>
                val calc = myTimer { (1 to 100000).sum }
                val result = calc + 10 // calc must be Int
                self reply (result)

            case 'String =>
                val calc = myTimer { (1 to 100000).mkString }
                val result = calc + " String" // calc must be String
                self reply (result)
}

现在,这是我得到的最远的:

trait Timing {
   def time[T <: Any](name: Symbol)(op: => T) :T = {
      val start = System.nanoTime
      val result = op
      val elapsed = System.nanoTime - start
      println(name + ": " + elapsed) 
      result
  }

  def mkTimer[T <: Any](name: Symbol) : (() => T) => () => T = {
      type c = () => T
      time(name)(_ : c)
  }
}

使用time函数直接工作,编译器正确使用匿名函数的返回类型来键入'time'函数:

val bigString = time('timerBigString) {
    (1 to 100000).mkString("-")
}
println (bigString)

看起来很棒,这种模式有许多缺点:

  • 强制用户在每次调用时重用相同的符号
  • 使得更高级的东西变得更加困难,比如预定义的项目级定时器
  • 不允许库初始化一次'timerBigString的数据结构

所以这里是mkTimer,它允许我部分应用时间函数并重用它。 我像这样使用mkTimer:

val myTimer = mkTimer('aTimer)
val myString= myTimer {
    (1 to 100000).mkString("-")
}
println (myString)

但是我收到编译错误:

error: type mismatch;
found   : String
required: () => Nothing
(1 to 100000).mkString("-")

如果我内联curry,我会得到同样的错误:

val timerBigString = time('timerBigString) _ 
val bigString = timerBigString  {
    (1 to 100000).mkString("-")
}
println (bigString)

如果我执行val timerBigString = time('timerBigString) (_: String) ,这是有效的,但这不是我想要的。 我想推迟部分应用函数的输入直到应用程序。

我得出结论,编译器在我第一次创建它时决定部分函数的返回类型,选择“Nothing”因为它无法做出更明智的选择。

所以我想我正在寻找的是一种对部分应用函数的后期绑定。 有没有办法做到这一点? 或许我可以遵循一条完全不同的道路?

好吧,感谢您阅读这篇文章

-TeO

当你想要“懒惰”泛型时,通常的模式是使用带有apply方法的类

class Timer(name: Symbol) {
  def apply[T](op: => T) = time(name)(op)
}
def mkTimer(name: Symbol) = new Timer(name)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM