Haskell и Scrypt: как получить зашифрованный хэш

#haskell #scrypt #io-monad

#haskell #scrypt #io-монада

Вопрос:

* Извините за основной вопрос, только начал изучать Haskell.

Я пытаюсь написать функцию, которая получит строку и вернет зашифрованный хэш.

На данный момент я пришел к следующему:

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

Однако я получаю сообщение об ошибке:

Couldn't match expected typeByteString
              with actual typeIO ByteStringIn 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 }
  

Есть идеи, как я могу избавиться от ввода-вывода?

Спасибо!

Комментарии:

1. Вы не можете избавиться от ввода-вывода (без использования darkest magic или путем вызова другого библиотечного метода). Скорее исправьте свой тип: ByteString -> IO ByteString

2. О … хорошо. Как мне сохранить значение в базе данных? Т.е. далее у меня есть execute "INSERT INTO test VALUES ... то, с чем я хочу использовать зашифрованное значение.

3. Если это дальше по строке IO также является операцией, просто поместите их оба в do выражение.

Ответ №1:

Вместо того, чтобы избавляться от IO , вам нужно настроить encrypt возврат an IO ByteString . encryptPassIO' для соли нужны случайные данные, которые она получает от IO монады, поэтому вы застряли там.

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

Вместо do обозначения я использовал encryptPassIO' . Pass для получения IO EncryptedPass значения из аргумента. Затем мы используем fmap для подъема getEncryptedPass :: EncryptedPass -> ByteString в IO монаду.

Вы могли бы использовать do нотацию, но IMO fmap делает это более чистым:

 encrypt pass = do
    x <- encryptPassIO' pass
    return (getEncryptedPass x)