【发布时间】:2016-03-09 03:55:26
【问题描述】:
我有一个管理Items 的应用程序。当客户端通过一些info 查询项目时,应用程序首先尝试使用该信息在数据库中查找现有项目。如果没有,应用程序会
检查
info是否有效。这是一项代价高昂的操作(比数据库查找要贵得多),因此应用仅在数据库中不存在现有项目时执行此操作。如果
info有效,则将新的Item插入到带有info的数据库中。
还有两个类,ItemDao 和 ItemService:
object ItemDao {
def findByInfo(info: Info): Future[Option[Item]] = ...
// This DOES NOT validate info; it assumes info is valid
def insertIfNotExists(info: Info): Future[Item] = ...
}
object ItemService {
// Very expensive
def isValidInfo(info: Info): Future[Boolean] = ...
// Ugly
def findByInfo(info: Info): Future[Option[Item]] = {
ItemDao.findByInfo(info) flatMap { maybeItem =>
if (maybeItem.isDefined)
Future.successful(maybeItem)
else
isValidInfo(info) flatMap {
if (_) ItemDao.insertIfNotExists(info) map (Some(_))
else Future.successful(None)
}
}
}
}
ItemService.findByInfo(info: Info) 方法非常丑陋。我一直在尝试清理它一段时间,但这很困难,因为涉及三种类型(Future[Boolean]、Future[Item] 和Future[Option[Item]])。我尝试使用scalaz 的OptionT 来清理它,但非可选的Futures 也不太容易。
关于更优雅的实现有什么想法吗?
【问题讨论】:
-
你有没有看过
lifting 你的非Option期货进入 monad 转换器? -
@badcook 你能详细点吗?
-
@badcook 我明白你的意思。我必须自己编写提升函数(这很简单)还是可以使用现有的 scalaz 函数?
-
Scalaz 应该有一个可以调用的
.liftM[OptionT]方法(您可能需要类型注释来帮助 Scala 的类型检查器)。