Как избежать подъема в MaybeT и почему окончательная проверка неэффективна? - PullRequest
1 голос
/ 08 января 2020

Как мы можем избежать - если это имеет смысл сделать ... - использование lift в MaybeT?

Классический пример из вики-книг .

Учитывая

isValid :: String -> Bool
isValid s = length s >= 8
            && any isAlpha s
            && any isNumber s
            && any isPunctuation s

У нас есть

getPassphrase :: MaybeT IO String
getPassphrase = do s <- lift getLine
                   guard (isValid s) -- Alternative provides guard.
                   return s

askPassphrase :: MaybeT IO ()
askPassphrase = do lift $ putStrLn "Insert your new passphrase:"
                   value <- getPassphrase
                   lift $ putStrLn "Storing in database..."

То, что я пробовал

Я думаю, мне нужно использовать ask и tell, поэтому я Код был преобразован следующим образом:

getPassphrase :: MaybeT (ReaderT String IO) String
getPassphrase = do 
        s <- ask
        guard (isValid s) -- Alternative provides guard.
        return s

askPassphrase :: MaybeT (ReaderT String IO) ()
askPassphrase = do 
  -- _ <- tell "Insert your new passphrase:"
  value <-  getPassphrase
  -- _ <- tell "Storing in database..."
  return ()



main :: IO (Maybe ())
main =
  runReaderT (runMaybeT askPassphrase) "test123!"

Строка "test123!" создает Just(), а "test123" возвращает Nothing, поэтому IMO работает должным образом, но я все еще имею включить Writer.

Если я делаю

askPassphrase :: MaybeT (ReaderT String (WriterT String IO)) ()
askPassphrase = do 
  _ <- tell "Insert your new passphrase:"
  let value =  getPassphrase
  _ <- tell "Storing in database..."
  return ()



main :: IO ()
main =
  execWriterT (runReaderT (runMaybeT askPassphrase) "test123!") >>= putStrLn

, он компилируется и запускается, но что-то идет не так, потому что любая строка считается допустимой, я имею в виду, что я всегда вижу "Insert your new passphrase:Storing in database..." на выходе. Чего мне не хватает?

1 Ответ

1 голос
/ 08 января 2020

Мне просто нужно было найти правильные типы моих функций с помощью команды :t и затем указать их, они

getPassphrase :: MaybeT (ReaderT String (WriterT String IO)) [Char]
getPassphrase = do

и

askPassphrase :: MaybeT (ReaderT String (WriterT String IO)) ()
askPassphrase = do 

И lift можно избежать ! (ask был уже без lift во второй части вопроса)

askPassphrase = do 
  tell "Insert your new passphrase:"
  value <-  getPassphrase
  tell "Storing in database..."

Онлайн версия здесь .

...