Scala monad在未来的[T]中携带HTTP url/params
我在scala中实现了以下monad,它用请求使用的URL和参数包装了一个分派结果Scala monad在未来的[T]中携带HTTP url/params,scala,monads,json4s,Scala,Monads,Json4s,我在scala中实现了以下monad,它用请求使用的URL和参数包装了一个分派结果 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 execution
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 )
}
我遇到的问题是flatmap
的定义。要使flatmap
正确,url
和params
需要来自f
,即f:T=>Result[S]
。在上面的例子中,虽然编译得很好,签名正是我所需要的,但是self.url
和self.params
意味着url
和params
永远不会用flatMap
编辑的结果更新,当调用flatMap
时,我不知道如何从f
的应用程序中获取url
和param
变量
虽然T
对于请求[S]
是必需的,但是url
和params
不需要它,那么如何将url,params
从结果
中分离出来,这样我就可以正确地定义flatMap
注:monad的一般用途是,我可以处理分派的HTTP
结果(即Future[T]
),同时能够携带用于请求的url
和params
,并使用flatmap
更新url
、params
和result
(这是一个新请求),其中as映射只需修改结果
编辑:下面是我目前如何使用monad的一个例子
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
val response=for{
标记s}.head
})//键入Result[String],映射正在处理请求[JValue]中的Future[JValue]中的'JValue'
someDataflatMap的规范定义是:
def flatMap(f: A => M[B]): M[B]
这在本质上是确定的。在你的例子中,你试图在一个动作上强加一个确定性的组合,其中所需的值是以非确定性的方式给出的。因此,你的麻烦
如果您想以确定的方式回到这一点,您必须使用wait
def flatMap[B](f: A => Result[B]): Result[B] = Await result (result map f)
这完全完全违背了最初使用未来的目的。描述对象特征的更好方法是简单地从内部移除未来
,并从外部将其封闭:
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]
。如果将flatMap
的计算建立在非确定性结果的基础上,那么听起来你并没有真正的确定性flatMap
。因此,您不能按照自己的意愿编写flatMap
。scala中的惯用方法是什么来解决我试图解决的问题?(也就是说,url
和params
是确定性的,result
不是。问题是它实际上没有回答我的原始问题,即能够使用(例如),为了理解一个类型结果[T]
,在最后能够用您的解决方案检索结果
以及url
和参数
时,我必须打开未来[T]
来进行任何理解,这意味着我丢失了url
和params
编辑了原始问题,并举例说明了如何使用Result[T]
monad