title: Reduce IO (Maybe (IO (Maybe a)) to IO (Maybe a)
body: <p>I have a function that reads an Rsa key with the HsOpenSsl's <code>readPrivateKey</code> function unfortunately the signature of my function is this <code>String -&gt; IO (Maybe (IO Maybe RsaKey))</code>. I need the PEM format and a Cryptonite.RSA key and I wrote the function <code>mkRsaKey</code> to make that from a string in PEM format.</p>
  <p>Heres the code:</p>
  <pre><code>import qualified Crypto.PubKey.RSA as Rsa --from cryptonite
  import OpenSSL.EVP.PKey -- from HsOpenSSL
  import OpenSSL.PEM -- from HsOpenSSL
  import OpenSSL.RSA -- from HsOpenSSL
  import Prelude
  
  data RsaKey = RsaKey
    { rsaKeyCryptoniteKey :: Rsa.PrivateKey,
      rsaKeyStringRepr :: String
    }
    deriving (Show)
  
  openSslKeyToCryptoniteKey :: RSAKeyPair -&gt; Maybe Rsa.PrivateKey
  openSslKeyToCryptoniteKey key = do
    let d = rsaD key
    let p = rsaP key
    let q = rsaQ key
    let mdP = rsaDMP1 key
    let mdQ = rsaDMQ1 key
    let mqinv = rsaIQMP key
    let size = rsaSize key
    let n = rsaN key
    let e = rsaE key
    dP &lt;- mdP
    dQ &lt;- mdQ
    qinv &lt;- mqinv
  
    let pub = Rsa.PublicKey size n e
    return $ Rsa.PrivateKey pub d p q dP dQ qinv
  
  openSslKeyToRsaKey :: RSAKeyPair -&gt; IO (Maybe RsaKey)
  openSslKeyToRsaKey key = do
    stringRepr &lt;- writePublicKey key
    let maybeCryptoKey = openSslKeyToCryptoniteKey key
    return $ do
      cryptoKey &lt;- maybeCryptoKey
      return $ RsaKey cryptoKey stringRepr
  
  mkRsaKey :: String -&gt; IO (Maybe (IO (Maybe RsaKey)))
  mkRsaKey privateKey = do
    someOpenSslKey &lt;- readPrivateKey privateKey PwNone
    let openSslKey = toKeyPair someOpenSslKey
    return $ openSslKeyToRsaKey &lt;$&gt; openSslKey
  </code></pre>
  <p>Now as you can see the type signature is in my sense not optimal I would like to have <code>IO (Maybe RsaKey)</code>. How can I achieve this?</p>
  <h2>EDIT:</h2>
  <p>I actually managed to do it but I'm using <code>unsafePerformIO</code>:</p>
  <pre><code>mkRsaKey :: String -&gt; IO (Maybe RsaKey)
  mkRsaKey privateKey = do
    someOpenSslKey &lt;- readPrivateKey privateKey PwNone
    return $ do
      openSslKey &lt;- toKeyPair someOpenSslKey
      unsafePerformIO (openSslKeyToRsaKey $ openSslKey)
  </code></pre>
  <p>As far as I know you should never use <code>unsafePerformIO</code> would there be some way to do this without it?</p>