Simão Martins
Simão Martins

Reputation: 1240

How to implement map/flatmap in a custom class

I have a class called Expect, after you instantiate it you can build a data structure (for simplicity lets say its a tree). Then you invoke the run method that traverses the tree executing some actions on each node. These actions take some time to complete so the final result is returned in a future. In pseudo-code it would be something like:

class Expect[R](command: String) {
  //some methods to build the tree

  def run()(implicit ec: ExecutionContext): Future[R] = {
    //Traverse the tree and execute actions on the nodes that eventually return a R
  }
}

I want to implement map and flatmap with their usual signatures but the functions they receive as argument must operate over the value returned in the future. And I cannot see any way of implementing this.

def map[T](f: R => T): Expect[T]
def flatMap[T](f: R => Expect[T]): Expect[T]

Upvotes: 1

Views: 1370

Answers (1)

stew
stew

Reputation: 11366

following the types leads me to this:

import scala.concurrent.{ExecutionContext, Future}

abstract class Expect[R](command: String) { self => 
  //some methods to build the tree

  def run(implicit ec: ExecutionContext): Future[R]

  def map[T](f: R => T): Expect[T] = new Expect[T](command) {
    def run(implicit ec: ExecutionContext): Future[T] =
      self.run.map(f)
  }

  def flatMap[T](f: R => Expect[T]): Expect[T] = new Expect[T](command) {
    def run(implicit ec: ExecutionContext): Future[T] =
      self.run.flatMap(r => f(r).run)
  }
}

I think that command probably doesn't belong in the constructor, it probably just needs to be closed over by structural refinements which actually use the command string

Upvotes: 5

Related Questions