【发布时间】:2013-02-15 17:58:49
【问题描述】:
我有一个代表数据库记录的字符串 id 列表。我想从数据库异步加载它们,然后将每条记录异步上传到远程服务器,然后当所有上传完成后,记录上传记录的ID。
由于我使用的是 Scala 2.9.2,因此我使用的是 Twitter 的 core-util Future 实现,但它在 Monadic 转换方面应该与 2.10 的 future 完全一样。
一般概念是这样的:
def fetch(id: String): Future[Option[Record]]
def upload(record: Record): Future[String]
def notifyUploaded(ids: Seq[String]): Unit
val ids: Seq[String] = ....
我正在尝试通过 for 理解来做到这一点,但 fetch 返回 Option 的 Future 的事实使它变得晦涩难懂并且代码无法编译:
for {
id <- ids
maybeRecord <- fetch(id)
record <- maybeRecord
uploadedId <- upload(record)
} yield uploadedId
编译它会导致以下错误:
scala: type mismatch;
found : com.twitter.util.Future[String]
required: Option[?]
uploadedId <- upload(record)
^
我错过了什么?为什么编译器期望 uploadId 是一个选项?有什么漂亮的方法可以解决这个问题吗?
【问题讨论】:
-
Monad 是 Endo 类中的 Monoid。只是说'
-
@folone:我担心不是每个人都会得到joke。只是说'
-
@folone 但问题是自然转换是从两个内函子到自身的乘积,而不是它们本身就是内函子。
-
@folone 因此,每个 monad 都是 Scala 类型类别上的 endofunctors 类别中的一个对象。在该类别中,态射是函子之间的自然转换,而被破坏的是“flatMap/bind”的自然转换来自
M x M -> M,而组合它就像M x T -> TM(例如函子。)问题是不能保证(而且通常不是真的)组合本身就是一个单子。