Reputation: 1240
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
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