0

*Sorry for the basic question, just started learning Haskell.

I am trying to write a function that will get a string and return an encrypted hash.

What I have come up with for the moment is:

encrypt :: ByteString -> ByteString
encrypt = do
    x <- Crypto.Scrypt.encryptPassIO' (Pass "secret")
    fmap Crypto.Scrypt.getEncryptedPass x

However I get the error:

• Couldn't match expected type ‘ByteString’
              with actual type ‘IO ByteString’
• In a stmt of a 'do' block: x <- encryptPassIO' (Pass plain)
  In the expression:
    do { x <- encryptPassIO' (Pass plain);
         fmap Crypto.Scrypt.getEncryptedPass x }
  In an equation for ‘encrypt’:
      encrypt plain
        = do { x <- encryptPassIO' (Pass plain);
               fmap Crypto.Scrypt.getEncryptedPass x }

Any idea how I can get rid of the IO?

Thanks!

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 2
    You cannot get rid of IO (without using darkest magic, or by calling another library method). Rather, fix your type: `ByteString -> IO ByteString` – Bergi Oct 17 '16 at 22:11
  • Oh... ok. How do I save the value to the database then? I.e. further down I have `execute "INSERT INTO test VALUES ...` that I want to use the encrypted value with. –  Oct 17 '16 at 22:17
  • 1
    If that further down the line is an `IO` operation as well, just put both of them in a `do` expression. – Bergi Oct 17 '16 at 22:24

1 Answers1

3

Rather than getting rid of the IO, you need to adjust encrypt to return an IO ByteString. encryptPassIO' needs random data to use for the salt, which it gets from the IO monad, so you are stuck there.

import Crypto.Scrypt (encryptPassIO', getEncryptedPass)
encrypt :: ByteString -> IO ByteString
encrypt = fmap getEncryptedPass . encryptPassIO' . Pass

Instead of do notation, I've used encryptPassIO' . Pass to get the IO EncryptedPass value from the argument. We then use fmap to lift getEncryptedPass :: EncryptedPass -> ByteString into the IO monad.

You could use do notation, but IMO fmap makes this cleaner:

encrypt pass = do
    x <- encryptPassIO' pass
    return (getEncryptedPass x)
chepner
  • 497,756
  • 71
  • 530
  • 681