Code with many "early returns (exits)" into the functional style
After reading the code, I assume these are the signatures of the building blocks of your code

class IdInfo
class PasswordInfo
class ConnectionInfo

def calcIdInfo:IdInfo=???
def calcPwdInfo(idInfo:IdInfo):PasswordInfo=???
def calcConnInfo(idInfo:IdInfo,pwdInfo:PasswordInfo):PasswordInfo=???


I left out the implementations for the calc as they don't really matter.

There are several possible variations to improve on the current code. Let's have a look at the last call to  map in connect  : 

 connInfoOpt map (connInfo =&gt; {
    try {
      verify(idInfo, pwdInfo, connInfo)
      Some(idInfo, pwdInfo, connInfo)
    } catch {
      case ex: IOException =&gt; None
      case ex: AuthorizationException =&gt; None
    }
  }) getOrElse None


The try expression has type Option[(IdInfo, PasswordInfo, ConnectionInfo)] which is the type you want as the output of the function connect. As the name connInfoOpt suggests, it is also an option. Map on option has a signature roughly equivalent to : 

map(f:A=&gt;B):Option[B]


Where A is the type which is wrapped in the original option, and B is the type wrapped in the resulting option. 

Thus let's say connInfoOpt has type Option[ConnectionInfo] we get 

A = ConnectionInfo
B = Option[(IdInfo, PasswordInfo, ConnectionInfo)]


Therefore the return type of the map expression is Option[B] which can be expanded to 

Option[Option[(IdInfo, PasswordInfo, ConnectionInfo)]]


Here lies the first problem : to get the Option[(IdInfo, PasswordInfo, ConnectionInfo)] out, you use getOrElse None. A slightly shorter way to express that is to call flatten. 

The original expression can thus be rewritten as: 

 connInfoOpt map (connInfo =&gt; {
    try {
      verify(idInfo, pwdInfo, connInfo)
      Some(idInfo, pwdInfo, connInfo)
    } catch {
      case ex: IOException =&gt; None
      case ex: AuthorizationException =&gt; None
    }
  }) flatten


which has type Option[(IdInfo, PasswordInfo, ConnectionInfo)]. The next step is to study the option type and see that it has a flatMap method which has the following signature :

flatMap(f:A=&gt;Option[B]):Option[B]
// for comparison with map which was 
map(f:A=&gt;B):Option[B]


Then notice that each intermediary is step is of the form  : 

option map { A=&gt; Option[B] } flatten


for instance: 

connInfoOpt map (connInfo =&gt; {
  try {
    verify(idInfo, pwdInfo, connInfo)
    Some(idInfo, pwdInfo, connInfo)
  } catch {
    case ex: IOException =&gt; None
    case ex: AuthorizationException =&gt; None
  }
}) flatten


can be rewritten as : 

connInfoOpt flatMap (connInfo =&gt; {
  try {
    verify(idInfo, pwdInfo, connInfo)
    Some(idInfo, pwdInfo, connInfo)
  } catch {
    case ex: IOException =&gt; None
    case ex: AuthorizationException =&gt; None
  }
})


Which means the whole function can now be simplified to : 

 def connect(): Option[(IdInfo, PasswordInfo, ConnectionInfo)] = {
    val idInfoOpt = try {
      Some(calcIdInfo())
    } catch {
      case ex: IOException =&gt; None
    }

    idInfoOpt flatMap (idInfo =&gt; {
      val pwdInfoOpt = try {
        Some(calcPwdInfo(idInfo))
      } catch {
        case ex: AuthorizationException =&gt; None
      }

      pwdInfoOpt flatMap (pwdInfo =&gt; {
        val connInfoOpt = try {
          Some(calcConnInfo(idInfo, pwdInfo))
        } catch {
          case ex: IOException =&gt; None
        }

        connInfoOpt flatMap (connInfo =&gt; {
          try {
            verify(idInfo, pwdInfo, connInfo)
            Some(idInfo, pwdInfo, connInfo)
          } catch {
            case ex: IOException =&gt; None
            case ex: AuthorizationException =&gt; None
          }
        })
      })
    })
  }


We got rid of the 3 getOrElse but this still isn't so nice. Let's extract a few methods next to make the code easier to read :

def safeIdInfo():Option[IdInfo]={
  try {
    Some(calcIdInfo())
  } catch {
    case ex: IOException =&gt; None
  }
}

def verifyConnInfo(idInfo: IdInfo, pwdInfo: PasswordInfo, connInfo: ConnectionInfo) :Option[(IdInfo, PasswordInfo, ConnectionInfo)] = {
  try {
    verify(idInfo, pwdInfo, connInfo)
    Some(idInfo, pwdInfo, connInfo)
  } catch {
    case ex: IOException =&gt; None
    case ex: AuthorizationException =&gt; None
  }
}

def safeConnInfo(idInfo: IdInfo, pwdInfo: PasswordInfo): Option[ConnectionInfo] = {
  try {
    Some(calcConnInfo(idInfo, pwdInfo))
  } catch {
    case ex: IOException =&gt; None
  }
}

def safePwdInfo(idInfo: IdInfo): Option[PasswordInfo] = {
  try {
    Some(calcPwdInfo(idInfo))
  } catch {
    case ex: AuthorizationException =&gt; None
  }
}


then the connect method looks like : 

def connect(): Option[(IdInfo, PasswordInfo, ConnectionInfo)] = {
  safeIdInfo() flatMap (idInfo =&gt;
    safePwdInfo(idInfo) flatMap (pwdInfo=&gt;
      safeConnInfo(idInfo, pwdInfo) flatMap (connInfo =&gt;
        verifyConnInfo(idInfo, pwdInfo, connInfo)
      )
    )
  )
}


Which is better but not perfect. Let's apply some scala syntactic sugar : 

def connect(): Option[(IdInfo, PasswordInfo, ConnectionInfo)] = {    
  for{
    idInfo   &lt;- safeIdInfo()
    pwdInfo  &lt;- safePwdInfo(idInfo)
    connInfo &lt;- safeConnInfo(idInfo, pwdInfo)
    verified &lt;- verifyConnInfo(idInfo, pwdInfo, connInfo)
  } yield verified 
}  


The connect method is much better (I think) but we end up with repetition in the "safe" methods. Actually, Scala offers a type to reduce this duplication, the Try type which we will use to replace the Option type in the "safe" methods :

def verifyConnInfo(idInfo: IdInfo, pwdInfo: PasswordInfo, connInfo: ConnectionInfo) :Try[(IdInfo, PasswordInfo, ConnectionInfo)] = Try {
  verify(idInfo, pwdInfo, connInfo)
  (idInfo, pwdInfo, connInfo)
}
def safeIdInfo():Try[IdInfo]=Try(calcIdInfo())    
def safeConnInfo(idInfo: IdInfo, pwdInfo: PasswordInfo): Try[ConnectionInfo] = Try(calcConnInfo(idInfo, pwdInfo))
def safePwdInfo(idInfo: IdInfo): Try[PasswordInfo] = Try(calcPwdInfo(idInfo))


Of course doing this, the connect method is no longer valid at the type level it needs to be adapted. To match the exact behavior of the original code the adaptation will look like : 

  def connect(): Option[(IdInfo, PasswordInfo, ConnectionInfo)] = {    
    val tryVerified = for{
      idInfo &lt;- safeIdInfo()
      pwdInfo &lt;-  safePwdInfo(idInfo)
      connInfo &lt;- safeConnInfo(idInfo, pwdInfo)
      verified &lt;- verifyConnInfo(idInfo, pwdInfo, connInfo)
    } yield verified

    tryVerified match {
      case Success(value) =&gt; Some(value)
      case Failure(authException:AuthorizationException)=&gt; None
      case Failure(ioException:IOException)=&gt; None
      case Failure(failed)=&gt; throw failed
    }
  }  


However I will suppose that you don't really want to rethrow unknown runtime exceptions and instead want to return None for any error, in which case the following form of connect should work : 

  def connect(): Option[(IdInfo, PasswordInfo, ConnectionInfo)] = {    
    val tryVerified = for{
      idInfo &lt;- safeIdInfo()
      pwdInfo &lt;-  safePwdInfo(idInfo)
      connInfo &lt;- safeConnInfo(idInfo, pwdInfo)
      verified &lt;- verifyConnInfo(idInfo, pwdInfo, connInfo)
    } yield verified

    tryVerified.toOption
  }  


The complete code is now :

 def verifyConnInfo(idInfo: IdInfo, pwdInfo: PasswordInfo, connInfo: ConnectionInfo) :Try[(IdInfo, PasswordInfo, ConnectionInfo)] = Try {
    verify(idInfo, pwdInfo, connInfo)
    (idInfo, pwdInfo, connInfo)
  }
  def safeIdInfo():Try[IdInfo]=Try(calcIdInfo())
  def safeConnInfo(idInfo: IdInfo, pwdInfo: PasswordInfo): Try[ConnectionInfo] = Try(calcConnInfo(idInfo, pwdInfo))
  def safePwdInfo(idInfo: IdInfo): Try[PasswordInfo] = Try(calcPwdInfo(idInfo))

  def connect(): Option[(IdInfo, PasswordInfo, ConnectionInfo)] = {    
    val tryVerified = for{
      idInfo &lt;- safeIdInfo()
      pwdInfo &lt;-  safePwdInfo(idInfo)
      connInfo &lt;- safeConnInfo(idInfo, pwdInfo)
      verified &lt;- verifyConnInfo(idInfo, pwdInfo, connInfo)
    } yield verified

    tryVerified.toOption
  }  


Using the right types, a functional style and some syntactic sugar can go a long way to simplify your code :)

For further reference, check the scala doc for Option and Try, also check out the FAQ on yield for more explanations on the for-expression syntactic sugar.