我正在浏览https://en.wikibooks.org/wiki/Haskell/Monad_transformers
的教程我写下了一段代码。一个没有和其他MonadTransformer
实例:
-- Simple Get Password functions.
getPassphrase1 :: IO (Maybe String)
getPassphrase1 = do
password <- getLine
if isValid password
then return $ Just password
else return Nothing
askPassphrase1 :: IO ()
askPassphrase1 = do
putStrLn "Enter password < 8 , alpha, number and punctuation:"
p <- getPassphrase1
case p of
Nothing -> do -- Q1. ### How to implement this with `MonadTrans` ?
putStrLn "Invalid password. Enter again:"
askPassphrase1
Just password ->
putStrLn $ "Your password is " ++ password
-- The validation test could be anything we want it to be.
isValid :: String -> Bool
isValid s = length s >= 8
&& any isAlpha s
&& any isNumber s
&& any isPunctuation s
另一个人使用我自己写的MonadT
。
getPassphrase2 :: MaybeT IO String
getPassphrase2 = do
password <- lift getLine
guard $ isValid password
return password
askPassphrase2 :: MaybeT IO ()
askPassphrase2 = do
lift $ putStrLn "Enter password < 8 , alpha, number and punctuation:"
p <- getPassphrase2
-- Q1. How to print "Invalid password" ?
lift $ putStrLn $ "Your password is " ++ p
-- The validation test could be anything we want it to be.
isValid :: String -> Bool
isValid s = length s >= 8
&& any isAlpha s
&& any isNumber s
&& any isPunctuation s
main :: IO ()
main = do
a <- runMaybeT askPassphrase2
return ()
两者都有效。
但我无法理解如何在wrong password
示例中添加MonadTrans
支持。 ?
另外,main
方法是正确的吗?还是可以用更好的方式编写?
答案 0 :(得分:1)
guard
不是你在MaybeT方法中想要的。要检查无效密码和是否能够提供您自己的处理,您只需使用原始版本的getPassphase
并将提升到MaybeT IO
monad:
getPassphease2 = do result <- lift $ getPassphrase1
case result of
Nothing -> lift $ putStrLn "bad password"
Just pw -> lift $ putStrLn "your password is: " ++ pw
...说明
MaybeT IO
monad用于为IO-actions提供失败和失败的能力,monad会自动处理该失败。如果任何步骤失败,控制将一直返回runMaybeT
和runMaybeT
返回Nothing
。这就像抛出异常一样。
使用MaybeT
的要点是您不必显式检查步骤是否失败 - 在调用每个步骤后由MaybeT
monad执行检查。这意味着你可以编写代码,假设每个前面的步骤都已成功 - 即好像你在#34;愉快的路径&#34;。这也意味着如果上一步失败,您就无法做出不同的事情。
使用MaybeT
getPassphrase
版main = do result <- runMaybeT askPassphrase2
case result of
Just _ -> return ()
Nothing -> putStrLn "Some failure happened... perhaps wrong password?"
的一种可能性是:
runMaybeT
问题在于,如果Nothing
返回askPassphrase
,则可能意味着guard
中的任何步骤都失败了,而不仅仅是getPassphrase
。
使用MaybeT版askPassphrase
的另一种方法是runMaybeT
使用askPassphrase2 = do result <- lift $ runMaybeT getPassphrase2
case result of
Nothing -> lift $ putStrLn "bad password"
Just pw -> lift $ putStrLn $ "Your password is " ++ pw
运行它:
runMaybeT
在这里,我们像使用try-catch块一样使用Push Notification
。