我在scala中实现了以下monad,它使用用于请求的URL和params包装调度结果
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
永远不会更新Result
正在flatMap
,换句话说,我不知道如何从{{1}的应用中获取url
和param
个变量当f
被调用时。
虽然flatMap
需要T
,但Request[S]
和url
并不需要{}},那么scala的分离方式是什么?来自params
的{{1}},因此我可以正确定义url,params
?
注意:monad背后的一般目的是这样我可以使用result
调度结果(即flatMap
),同时能够随身携带HTTP
和{{1}用于请求,Future[T]
更新url
,params
和flatMaps
(这是一个新请求),其中地图只修改url
编辑:以下是我目前如何使用monad
的示例params
请注意,之前,这个理解仅适用于result
,但是这样做会丢失使用的URL /参数
答案 0 :(得分:1)
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]
进入场景。