For comprehension that has to handle 2 optional values and return a Option[T]

For comprehension that has to handle 2 optional values and return a Option[T]

Problem Description:

The below code works fine, but as you can see the 2nd clause in the for comprehension has a call that is unsafe.

case class ProductView(product: Product, stores: List[Store], warehosue: Option[Warehosue])

def loadView(...): ConnectionIO[Option[ProductView]] = 
for {
   product <- getProductById(id)  // ConnectionIO[Option[Product]]
   warehouse <- getWarehouse( // ConnectionIO[Option[Warehouse]]
   stores <- loadStores(...)     // ConnectionIO[List[Store]]
} yield product map { p =>
    ProductView(p, stores, warehouse)   

I tried to make that a safe call, but my types don’t seem to line up.

   warehouse <- getWarehouse( 

How can I improve this, if any of the options is a None, I just want to return a None.
This is suppose to return a Option[Warehouse]

I tried this:

warehouse <- => => getWarehouse(id)))

Hoping someone can help with this part of my for comprehension.

Solution – 1

The easiest way is using OptionT and flatTraverse

def loadView(id: Int):
  ConnectionIO[Option[ProductView]] =
    (for {
      product <- OptionT(getProductById(id))
      warehouse <- OptionT.liftF(product.warehouseId.flatTraverse(getWarehouse))
      stores <- OptionT.liftF(loadStores(...))
    } yield ProductView(product, stores, warehouse)).value

Also alternative variant without OptionT

  def loadView(id: Int): ConnectionIO[Option[ProductView]] = {
    getProductById(id).flatMap {
      _.traverse { product =>
        for {
          warehouse <- product.warehouseId.flatTraverse(getWarehouse)
          stores <- loadStores(...)
        } yield ProductView(product, stores, warehouse)
Rate this post
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.