Scala monad在未来的[T]中携带HTTP url/params

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

我在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 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