我玩了! 2用于Scala应用程序,需要从外部服务检索JSON格式的某些数据 .
表演!框架允许通过将响应包装在_1281291中来异步发出HTTP请求 . Promise
是一个monad,它包含将来可用的值 .
这很好,但在我的情况下,我从Web服务得到的是一个JSON字符串 . 我必须解析它,解析可能会失败 . 所以我必须将我得到的任何内容包装成 Option
. 结果是我的许多方法都返回 Promise[Option[Whatever]]
. 也就是说,类型 Whatever
的值可能稍后可用 .
现在每当我必须操作这样的值时,我需要两次 map
. 我想用以下方式处理这个问题:
-
创建一个新类型,比如
Hope[A]
,包装Promise[Option[A]]
-
定义相关方法,如
map
(或者我应该使用foreach
并从某些集合特征继承?)和flatten
-
在
Promise[Option[A]]
和Hope[A]
之间提供隐式转换器 .
很容易定义 map
- 两个仿函数的组合又是一个仿函数 - 在这种情况下可以显式地完成 flatten
,或者在用 Option
组成monad时 .
But 这是我有限的理解,我不需要重新发明这些东西:monad变换器确实存在于这种情况下 . 或者,好吧,所以我认为 - 我从未使用过monad变换器 - 这就是问题的关键点:
在这种情况下可以使用monad变压器吗?我将如何实际使用它们?
2 回答
使用Scalaz库的
OptionT
转换器,您应该能够将Promise[Option[A]]
类型的值转换为OptionT[Promise, A]
类型的值 .使用Scalaz 7:
要使用此值,例如在其上调用
map
或flatMap
,您需要为Promise
(Functor
为map
,Monad
为flatMap
)提供适当的类型类 .由于
Promise
是monadic,因此应该可以提供Monad[Promise]
的实例 . (你将免费获得Functor
和Applicative
,因为类型类形成了一个继承层次结构 . )例如(注意:我没有测试过这个!):举个简单的例子,您现在可以在
OptionT[Promise, A]
上使用map
,将类型A => B
的函数应用于里面的值:要从
OptionT[Promise, A]
检索基础Promise[Option[A]]
值,请调用run
方法 .当您可以组合兼容类型的多个操作时,您将从使用monad变换器中获得更多好处,在操作之间保留
OptionT[Promise, _]
类型并在最后检索基础值 .要在for-comprehension中编写操作,您将需要
A => OptionT[Promise, B]
类型的函数 .编辑:
好的,你可以在这里使用
scalaz.OptionT
: