2016-06-11 24 views
0

我通過教程在https://en.wikibooks.org/wiki/Haskell/Monad_transformers理解MonadTransformer例子

要我寫了下面這段代碼。一個沒有和其他與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() 

這兩個作品。

但我無法理解如何在MonadTrans示例中添加wrong password支持。 ?

另外,是main方法好嗎..或者它可以寫得更好?

+1

如果您不打算使用它,則無需將值綁定到'a'; 'main = runMaybeT askPassphrase >> return()' – chepner

回答

1

guard是不是你想要的MaybeT方法。要檢查是否存在無效的密碼能夠提供在這種情況下,你自己處理,你只想用你原來getPassphase電梯它的版本到了MaybeT IO單子:

getPassphease2 = do result <- lift $ getPassphrase1 
        case result of 
         Nothing -> lift $ putStrLn "bad password" 
         Just pw -> lift $ putStrLn "your password is: " ++ pw 

解釋...

0123admonad用於使IO-操作具有失敗的能力由monad自動處理失敗。如果任何步驟失敗,則控制返回到runMaybeTrunMaybeT返回Nothing。這就像拋出一個異常。

使用MaybeT的要點是,您不必顯式檢查一個步驟是否失敗 - 在每個步驟被​​調用後由MaybeT monad執行檢查。這意味着你可以編寫代碼,假定每一個前面的步驟都成功了 - 也就是說,如果你在「快樂的路徑」上。這也意味着如果上一步失敗,你不能做出不同的事情。使用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版本的另一種方法是讓askPassphraserunMaybeT運行:

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塊。

+0

你可以給'askPassphrase'的最後一個例子'type'嗎?道歉爲兩個版本的功能相同的名稱..我沒有重新命名爲「1」和「2」。你還可以改變你的答案嗎? –

+0

完成 - 我在上一個代碼示例中修復了一個錯字。 – ErikR

+0

此外 - pehaps這個SO回答將幫助:http://stackoverflow.com/a/32582127/866915 – ErikR