用于理解的 ADT
ADT with for comprehension
我有一个用例,我需要在 Scala 中使用 ADT 进行理解。我可以使用 flatMaps 编写相同的代码,但它似乎有点不可读。下面是一段代码。
case class MovieRecord(movie: Movie,
screenId: String,
availableSeats: Int,
reservedSeats: Option[Int] = None) {
def movieInfo = new MovieInfoResponse(movie.imdbId, screenId, movie.title, availableSeats, reservedSeats.getOrElse(0))
}
sealed trait MovieBookingInformation
case class MovieBookingInformationFetched(bookMovie: MovieRecord) extends MovieBookingInformation
case object MovieBookingInformationFetchError extends MovieBookingInformation
def modifyBooking(reserveMovie: MovieSelected): Future[String] = {
fetchRecordByImdbAndScreenId(reserveMovie.imdbId, reserveMovie.screenId) flatMap {
case MovieBookingInformationFetched(m) if (m.availableSeats > 0) =>
updateSeatReservationByImdbAndScreenId(m.copy(availableSeats = m.availableSeats - 1, reservedSeats = Some(m.reservedSeats.getOrElse(0) + 1))) flatMap {
case MovieBookingUpdated(updatedMovieBooking) =>
Future.successful(s"One seat reserved at Screen - ${updatedMovieBooking.screenId}")
case MovieBookingUpdateFailed =>
Future.successful(s"Movie seat reservation failed at screen ${reserveMovie.screenId}")
}
case MovieBookingInformationFetched(m) =>
Future.successful(s"Sorry! No more seats available for ${m.movie.title} at Screen - ${m.screenId}")
case MovieBookingInformationFetchError => Future.successful(s"No movie with IMDB ID ${reserveMovie.imdbId} found at ${reserveMovie.screenId}")
}
}
在上面的代码中,对生成的 ADT 内容和 if 语句的结果调用 next 方法。如何在 for-comprehension 中包含 if 语句以实现相同的目的。
提前致谢。
您可以将模式匹配和 if
语句放在 Future
:
的 for comprehension 中
for {
MovieBookingInformationFetched(m) <- future1
if m.availableSeats > 0
MovieBookingUpdated(updatedMovieBooking) <- future2(m)
} yield updatedMovieBooking
但是,这会被翻译成Future.filter
,所以如果谓词不满足,或者模式无法匹配,你最终会得到
Future.failed(new NoSuchElementException("Future.filter predicate was not satisfied")
然后您可以在 for-comp 之后的 recover
语句中捕获此失败。问题是你想抓住三个不同的 "errors":没有更多可用座位的事实,fetchRecordByImdbAndScreenId
可以 return 和 MovieBookingInformationFetchError
的事实,以及 MovieBookingInformationFetchError
的事实updateSeatReservationByImdbAndScreenId
可以 return 一个 MovieBookingUpdateFailed
.
除非您定义自定义异常而不是自定义结果类型(并在之后恢复这些异常),否则您将无法仅使用理解来区分这三者。
我有一个用例,我需要在 Scala 中使用 ADT 进行理解。我可以使用 flatMaps 编写相同的代码,但它似乎有点不可读。下面是一段代码。
case class MovieRecord(movie: Movie,
screenId: String,
availableSeats: Int,
reservedSeats: Option[Int] = None) {
def movieInfo = new MovieInfoResponse(movie.imdbId, screenId, movie.title, availableSeats, reservedSeats.getOrElse(0))
}
sealed trait MovieBookingInformation
case class MovieBookingInformationFetched(bookMovie: MovieRecord) extends MovieBookingInformation
case object MovieBookingInformationFetchError extends MovieBookingInformation
def modifyBooking(reserveMovie: MovieSelected): Future[String] = {
fetchRecordByImdbAndScreenId(reserveMovie.imdbId, reserveMovie.screenId) flatMap {
case MovieBookingInformationFetched(m) if (m.availableSeats > 0) =>
updateSeatReservationByImdbAndScreenId(m.copy(availableSeats = m.availableSeats - 1, reservedSeats = Some(m.reservedSeats.getOrElse(0) + 1))) flatMap {
case MovieBookingUpdated(updatedMovieBooking) =>
Future.successful(s"One seat reserved at Screen - ${updatedMovieBooking.screenId}")
case MovieBookingUpdateFailed =>
Future.successful(s"Movie seat reservation failed at screen ${reserveMovie.screenId}")
}
case MovieBookingInformationFetched(m) =>
Future.successful(s"Sorry! No more seats available for ${m.movie.title} at Screen - ${m.screenId}")
case MovieBookingInformationFetchError => Future.successful(s"No movie with IMDB ID ${reserveMovie.imdbId} found at ${reserveMovie.screenId}")
}
}
在上面的代码中,对生成的 ADT 内容和 if 语句的结果调用 next 方法。如何在 for-comprehension 中包含 if 语句以实现相同的目的。
提前致谢。
您可以将模式匹配和 if
语句放在 Future
:
for {
MovieBookingInformationFetched(m) <- future1
if m.availableSeats > 0
MovieBookingUpdated(updatedMovieBooking) <- future2(m)
} yield updatedMovieBooking
但是,这会被翻译成Future.filter
,所以如果谓词不满足,或者模式无法匹配,你最终会得到
Future.failed(new NoSuchElementException("Future.filter predicate was not satisfied")
然后您可以在 for-comp 之后的 recover
语句中捕获此失败。问题是你想抓住三个不同的 "errors":没有更多可用座位的事实,fetchRecordByImdbAndScreenId
可以 return 和 MovieBookingInformationFetchError
的事实,以及 MovieBookingInformationFetchError
的事实updateSeatReservationByImdbAndScreenId
可以 return 一个 MovieBookingUpdateFailed
.
除非您定义自定义异常而不是自定义结果类型(并在之后恢复这些异常),否则您将无法仅使用理解来区分这三者。