---
# System prepended metadata

title: Question

---

# Question
Implement the function `retrieveAddress` using the methods `getStreet1`, `getStreet2`, and `getStreet3` to create an `Address`.
```scala
case class Address(
  street1: String,
  street2: Option[String],
  street3: Option[String]
)

def safeGetStreet1: IO[String] = IO(getStreet1)
def safeGetStreet2: IO[String] = IO(getStreet2)
def safeGetStreet3: IO[String] = IO(getStreet3)

(for {
    str1         <- safeGetStreet1
    str2: String <- safeGetStreet2.handleErrorWith(_ => new): Throwable => IO[B]   // B >: String
    str3         <- safeGetStreet3
} yield Address(str1, Some(str2), Some(str3))
 
// Address("Foo street 1", "Towncity", None)

def retrieveAddress: IO[Address] / Option[Address] / Try[Address] / Either[Throwable, Address] = {
    // TODO: Implement
    // Address(street1, Some(street2), Some(street3))
   
    val street2Opt: Option[String] = Try(getStreet2).toOption
    val street3Opt: Option[String] = Try(getStreet3).toOption
    
    Try(street1) match {
        case (Success(adr1)) =>
             IO.pure(Address(adr1, street2Opt, street3Opt))
        case (Failure(e))) =>
             IO.fail(e)    
    }
    
    
    
    IO(getStreet1).map(street1 =>
        Address(street1, street2Opt, street3Opt)
    )
}

def divide(x: Int, y: Int): IO[Int]     = if (y == 0) IO.fail(new Throwable(???)) else IO.pure(x / y)
def divide(x: Int, y: Int): Option[Int] = if (y == 0) IO.fail(new Throwable(???)) else IO.pure(x / y)
def divide(x: Int, y: Int): Int         = x / y // might throw DivideByZero
              
val x: Option[String] = Try(getStreet1) 
// Failure(e: Throwable) 
// Success(s: String)


// =======================================================================  
// LIBRARY METHODS 
// =======================================================================
/**
  * Retrieves the main street address.
  * @throws RuntimeException if empty
  */
def getStreet1: String = {
  // implementation
}
/**
  * Retrieves additional street address line 2.
  * @throws RuntimeException if empty
  */
def getStreet2: String = {
  // implementation
}
/**
  * Retrieves additional street address line 3.
  * @throws RuntimeException if empty
  */
def getStreet3: String = {
  // implementation
}

