2014-05-16 29 views
2

我在斯卡拉实施以下单子它包装调度结果与用于请求斯卡拉单子随身携带的未来[T]

import org.json4s._ 
import scala.concurrent.{ExecutionContext, Future} 

case class Result[T](url:String,params:JValue,result:Future[T]) { 
    self => 
    def flatMap[S](f: T => Result[S])(implicit executionContext:ExecutionContext):Result[S] = { 
    val result_ = f andThen (_.result) 
    Result(self.url,self.params,this.result flatMap result_) 
    } 

    def map[B](f: T => B)(implicit executionContext:ExecutionContext):Result[B] = 
    Result(this.url,this.params,this.result map f) 

} 

我这个问题的URL,而params HTTP URL/PARAMS具有flatmap的定义。对于flatmap是正确的,urlparams需要来自f,即f: T => Result[S]。在上面的例子中,虽然它编译得很好,并且签名正好是我需要的,但self.urlself.params意味着urlparams永远不会更新为Result,即flatMap ed,换句话说,我不知道当调用flatMap时,如何获得应用furlparam变量。

虽然T是必需的Request[S],它不是必需的urlparams,所以这将是分离出从resulturl,params的斯卡拉方式,所以我可以正确地定义flatMap

注:单子背后的一般目的是这样我就可以从调度HTTP结果工作(即Future[T]),同时能够携带用于请求urlparams各地,拥有flatMaps更新urlparamsresult (它是一个新的请求),其中的地图只是修改result

编辑:这里是我当前如何使用单子

val restResponse = for { 
    token <- Authenticate.Helpers.mainLogin // Type Result[String] 
    userSessionToken <- Authenticate.Helpers.loginToken("someUser","somePassword",token) // Type Result[String] 
    someOtherCommand <- DataService.getInitialData(token,userSessionToken) map 
     (_ \ "someData" \ "someMoreData" \\ "evenMoreData" match { 
      case JString(s) => s 
      case JArray(items) => 
      items.collectFirst { case JString(s) =>s}.head 
     }) // Type Result[String], the map is working over the `JValue` inside Future[JValue] that is held within the Request[JValue] 
    someData <- DataService.getData(token,userSessionToken) // Type Result[JValue] 
    } yield itemSummaries 

    println(restResponse.url) // should print the url of someData, but is instead printing the url of token. restResponse.result is the correct value however 
的例子0

注意之前,这对于理解只是工作过Future[T],然而,在这方面,我失去了使用

+0

如果您打算将“flatMap”的计算基于非确定性结果,那么您听起来并没有确定性的'flatMap'。因此,你不能写'flatMap',因为你想写它。 – wheaties

+0

什么是scala的惯用方式来解决我正在尝试解决的问题呢? (即用'params/url'来标记结果,同时能够将'result'作为单子?] 另外'url'和'params'是确定性的,'result'不是。 – mdedetrich

回答

1

的URL/PARAMS的flatMap的规范定义将是沿着线的东西:

def flatMap(f: A => M[B]): M[B] 

这是确定性的。在你的情况下,你试图强加一个确定性组合,而不是以一种非确定性的方式给出需要的值。因此,你的烦恼。

如果你想回到那个以确定的方式,你必须使用Await

def flatMap[B](f: A => Result[B]): Result[B] = Await result (result map f) 

这完全彻底的失败摆在首位使用Future的目的。一个更好的方法来描述你的对象是简单地从内从外删除Future和它括:

case class Result(url: String, params: JValue, result: T){ 
    def map[R](f: T => R) = copy(result = f(result)) 
    def flatMap[R](f: T => Result[R]) = f(result) 
} 

因此Future只能通过应用程序进入现场,以评估功能(String, JValue) => Result[T]异步。

+0

问题在于它实际上并没有回答我原来的问题,它可以使用(例如)理解类型Result [T]',而最终能够同时检索结果“以及”url“和”params“ 有了你的解决方案,我必须拆开'Future [T]'来完成任何理解,这意味着我失去了'url'和'params ' – mdedetrich

+0

编辑了一个我如何使用'Result [T]'monad的例子 – mdedetrich