如何使用可通过flatmap链接的错误标记令牌(如Option.None)构建Scala API?

时间:2015-08-06 23:18:54

标签: scala concurrency nothing

我最近尝试过对一些并发练习的修改 Functional Programming in Scala(好书,顺便说一句......早期版本可以免费下载!)。第7章涉及创建一个monadic类型构造函数Par [X],它允许任何类型X的表达式在与ExectutorService

配对时分叉并运行

我尝试的变体是创建一个API,允许调用者将并行表达式(参数化类型Par [X]的实例)平铺到一起。我想要一些与Option / Some / None类似的东西,其中如果其中一个flatmap结果恰好是一个失败(在Option的情况下是'None'),那么那个'冒泡'的失败就是top,这样构造链的调用者只需要检查顶级返回值是不是错误的sentinel。 (希望我想做的事情从这个解释清楚)。无论如何......我遇到了构造错误哨兵的问题。

我尝试以两种方式构建它,作为案例对象和案例类。在第一个例子中,case对象,我收到了这个错误

    Object creation impossible since member get():V in java.util.concurrent.future is not defined.

以下是第一个案例的代码:

    case object Failure extends Future[Nothing] {
    def isDone = true

    // why is compiler telling me i'm not defining this, when def'n is below?
    def get(timeout: Long, units: TimeUnit) =  
        throw new NoSuchElementException("nothing to get from failure")

    def isCancelled = false

    def cancel(evenIfRunning: Boolean): Boolean = false
    }

然后我尝试使用从Future [Nothing]扩展的case类,如下所示:

  case class Failure2 extends Future[Nothing] {
    def isDone = true

    def get(timeout: Long, units: TimeUnit) =  throw new NoSuchElementException("nothing to get from failure")

    def isCancelled = false

    def cancel(evenIfRunning: Boolean): Boolean = false
  }

这导致以下错误:

class Failure2 must be declared abstract or implement abstract member get():V in java.util.concurrent.future 

如果您有任何专家Scala API构建者可以帮助指导我的解决方案,我将非常感激!

2 个答案:

答案 0 :(得分:0)

当错误消息引用

  

get():V

中的成员java.util.concurrent.Future

他们指的是the get() method of Future with no arguments,你确实忘了实施。我猜你想要两个版本的get()做同样的事情。你只需要明确这一点。例如:

def get() = throw ...
def get(timeout: Long, units: TimeUnit) = get()

答案 1 :(得分:0)

这个答案补充了丹的答案,他指出了我的错误(谢谢,丹!)。我希望这个答案/评论可以帮助其他人避免同样被咬伤。当我编写了我的“失败”时。 case class / object我正在查看原始代码库中的一个case类,它以一种对我来说不明显的方式实现了Future的无参数get()。这是代码:

      private case class UnitFuture[A](get: A) extends Future[A] {
        def isDone = true

        def get(timeout: Long, units: TimeUnit) = get

        def isCancelled = false

        def cancel(evenIfRunning: Boolean): Boolean = false
      }

在这段代码中,无参数get()方法似乎是隐式实现的,因为get是case类构造函数的一个参数...我没有意识到这个方法就在那里,所以我忽略了在我的Failure类中实现它(因此我遇到的错误方法)。如果我很聪明,我会直接使用javadoc for Future来查看需要哪些方法....但我的假设是基于' UnitFuture'类,我错过了没有arg get()是该类的一部分的事实。好吧..生活和学习; ^)希望这有助于其他人不重复我的错误。