monad转换器是否适用于从服务获取JSON? [英] Do monad transformers apply to getting JSON from services?

查看:88
本文介绍了monad转换器是否适用于从服务获取JSON?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有戏!需要用于从外部服务检索JSON格式的某些数据的Scala应用程序2.

I have a Play! 2 for Scala application that needs to retrieve some data in JSON format from an external service.

戏剧!框架允许通过将响应包装在 Promise 中来异步发出HTTP请求. Promise是一个monad,它包装了将来将可用的值.

The Play! framework allows to make HTTP requests asynchronously by wrapping the response in a Promise. Promise is a monad that wraps a value that will be available in the future.

这很好,但就我而言,从Web服务获得的是JSON字符串.我必须解析它,解析可能会失败.因此,我必须将进入Option的所有内容包装起来.结果是我的许多方法都返回Promise[Option[Whatever]].也就是说,类型Whatever的值可能稍后会提供.

This is fine, but in my case what I get from the web service is a JSON string. I have to parse it and the parsing might fail. So I have to wrap whatever I get into an Option. The result is that many of my methods are returning Promise[Option[Whatever]]. That is, a value of type Whatever that will be, maybe, available later.

现在,每当我必须对这样的值进行运算时,都需要两次map.我正在考虑通过以下方式处理此问题:

Now whenever I have to operate over such a value I need to map it twice. I was thinking of handling this in the following way:

  • 创建一个新类型,例如Hope[A],该类型将包裹Promise[Option[A]]
  • 定义类似map的相关方法(或者也许我应该使用foreach并继承某些集合特征?)和flatten
  • Promise[Option[A]]Hope[A]之间提供隐式转换器.
  • creating a new type, say Hope[A], that wraps a Promise[Option[A]]
  • defining the relevant methods like map (or maybe I should use foreach and inherit from some collection trait?) and flatten
  • provide an implicit converter between Promise[Option[A]] and Hope[A].

定义map很容易-两个函子的组成又是一个函子-在这种情况下,或者每当用Option组成monad时,都可以明确地完成flatten.

It is easy to define map - the composition of two functors is again a functor - and flatten can be done explicitly in this case, or whenever composing a monad with Option.

但是据我所知,我不需要重新发明这些东西:在这种情况下,确实存在monad变压器.或者,好吧,所以我认为-我从未使用过monad变形金刚-这就是问题的重点:

But it is my limited understanding that I do not need to reinvent this stuff: monad transformer exist for exactly this case. Or, well, so I think - I have never used a monad tranformer - and this is the point of the question:

在这种情况下可以使用monad变压器吗?我将如何实际使用它们?

Can monad tranformers be used in this situation? How would I go about actually using them?

推荐答案

使用Scalaz库的OptionT转换器,您应该能够将Promise[Option[A]]类型的值转换为OptionT[Promise, A]类型的值.

Using the Scalaz library's OptionT transformer, you should be able to turn values of type Promise[Option[A]] into values of type OptionT[Promise, A].

使用Scalaz 7:

Using Scalaz 7:

import scalaz.OptionT._
val x: OptionT[Promise, Int] = optionT(Promise.pure(Some(123)))

要使用此值(例如,在其上调用mapflatMap,则需要为Promise提供适当的类型类(对于mapFunctor,对于flatMapMonad) ).

To use this value, for example to call map or flatMap on it, you will need to provide an appropriate typeclass for Promise (Functor for map, Monad for flatMap).

由于Promise是单原子的,因此应该可以提供Monad[Promise]的实例. (因为类型类形成继承层次结构,所以您将免费获得FunctorApplicative.)例如(注意:我尚未对此进行测试!):

Since Promise is monadic, it should be possible to provide an instance of Monad[Promise]. (You'll get Functor and Applicative for free, because the typeclasses form an inheritance hierarchy.) For example (note: I've not tested this!):

implicit val promiseMonad = new Monad[Promise] {
  def point[A](a: => A): Promise[A] = Promise.pure(a)
  def bind[A, B](fa: Promise[A])(f: A => Promise[B]): Promise[B] = fa flatMap f
}

作为一个简单的示例,您现在可以在OptionT[Promise, A]上使用map,将A => B类型的函数应用于内部值:

As a simple example, you can now use map on the OptionT[Promise, A], to apply a function of type A => B to the value inside:

def foo[A, B](x: OptionT[Promise, A], f: A => B): OptionT[Promise, B] = x map f

要从OptionT[Promise, A]中检索基础Promise[Option[A]]值,请调用run方法.

To retrieve the underlying Promise[Option[A]] value from an OptionT[Promise, A], call the run method.

def bar[A, B](x: Promise[Option[A]], f: A => B): Promise[Option[B]] =
  optionT(x).map(f).run

当您可以编写兼容类型的多个操作,在操作之间保留OptionT[Promise, _]类型并在最后获取基本值时,使用monad转换器将为您带来更多好处.

You will gain more benefit from using monad transformers when you can compose several operations of compatible types, preserving the OptionT[Promise, _] type between operations and retrieving the underlying value at the end.

要全面理解操作,您将需要类型为A => OptionT[Promise, B]的函数.

To compose operations in a for-comprehension, you will need functions of type A => OptionT[Promise, B].

这篇关于monad转换器是否适用于从服务获取JSON?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆