2014-05-16 30 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