不要单子变压器适用于从服务得到JSON?(Do monad transformers apply t

2019-07-31 07:46发布

我有一个玩游戏! 2为需要从外部服务检索JSON格式的某些数据的Scala应用。

表演! 框架允许通过包装的响应,使HTTP请求异步承诺 。 Promise是一个封装将在未来提供一个值的单子。

这是好的,但对我来说是我从网络服务得到的是一个JSON字符串。 我要分析它,并解析可能会失败。 所以,我必须包装无论我进入一个Option 。 其结果是,我的很多方法都返回Promise[Option[Whatever]] 。 也就是说,类型的值Whatever ,这将是,也许,以后可用。

现在,每当我有过这样的值来操作,我需要map两次吧。 我想的是通过以下方式处理这个:

  • 创建一个新的类型,说Hope[A]是一个包装了Promise[Option[A]]
  • 界定相关方法,如map (或者也许我应该使用foreach和继承一些收集特质?),并flatten
  • 提供之间的隐式转换器Promise[Option[A]]Hope[A]

这是很容易定义map -两个函子的成分又是一个函子-和flatten可以明确地在这种情况下进行,或撰写时用单子Option

它是我的,我不需要重新发明这个东西的理解有限:正是这种情况下单子转换存在。 或者说,好了,所以我想 - 我从来没有使用一个单子变压 - 这就是问题的要点:

可以单子发电产品在这种情况下使用? 我怎么会去实际使用的时候?

Answer 1:

使用Scalaz库的OptionT变压器,你应该能够把类型的值Promise[Option[A]]成类型的值OptionT[Promise, A]

使用Scalaz 7:

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

要使用此值,例如调用mapflatMap上它,你将需要为提供适当的类型类的PromiseFunctormapMonadflatMap )。

由于Promise是一元,应该能够提供的实例Monad[Promise] 。 (你会得到FunctorApplicative的自由,因为类型类形成的继承层次。)例如(注:我没有测试这一点):

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
}

作为一个简单的例子中,现在可以使用map上的OptionT[Promise, A]以类型的函数应用A => B里面的值:

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

要检索的基本Promise[Option[A]]从值OptionT[Promise, A]调用run方法。

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

您将获得使用单子变压器时,您可以撰写兼容类型的几种操作,保留更多的好处OptionT[Promise, _]操作之间的输入和检索末尾的潜在价值。

要撰写的换理解的操作,则需要类型的函数A => OptionT[Promise, B]



Answer 2:

- 删除 -

编辑:

没关系,你可以简单地使用scalaz.OptionT这里:

val x = optionT(Promise { /* api call */ some("""{ "foo": "bar" }""") })
val mapped = x.map(Json.parse).run // run return the resulting Promise[Option[T]]


文章来源: Do monad transformers apply to getting JSON from services?