Как мы можем избежать - если это имеет смысл - использования 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.
If I do
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..."
в выводе. Что мне не хватает?