2016-06-11 10 views
0

나는 코드의 조각 다음 썼다. 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 방식에서 원하는 것이 아닙니다. 잘못된 암호 를 확인하려면 방금하여 MaybeT IO 모나드에 getPassphase리프트을의 원래 버전을 사용하는 경우에 당신의 자신의 처리를 제공 할 수 :

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

설명을 ...

MaybeT IO 모나드는 IO 작업에 실패가있는 기능을 부여하기 위해 을 자동으로 처리합니다. 단계가 실패하면 제어는 runMaybeTrunMaybeT으로 돌아가고 Nothing을 반환합니다. 그것은 예외를 던지는 것과 같습니다.

MaybeT를 사용하는 포인트가 더 명시 적 단계에 오류가 있는지를 확인해야 할 것이 없다 - 각 단계가 호출 된 후 그 검사가 MaybeT 모나드에 의해 수행된다. 즉, 앞 단계가 성공했다는 가정하에 코드를 작성할 수 있습니다. 즉, 마치 "행복한 경로"에있는 것처럼 말입니다. 이것은 이전 단계가 실패한 경우 다른 작업을 수행 할 수 없다는 것을 의미합니다. getPassphraseMaybeT 버전을 사용

하나의 가능성은 이것이다 :

main = do result <- runMaybeT askPassphrase2 
      case result of 
      Just _ -> return() 
      Nothing -> putStrLn "Some failure happened... perhaps wrong password?" 

문제는 runMaybeT 반환 Nothing 경우는 askPassphrase의 모든 단계는 아니라 guard 실패했음을 의미 할 수 있다는 것입니다. 여기

askPassphrase2 = do result <- lift $ runMaybeT getPassphrase2 
        case result of 
         Nothing -> lift $ putStrLn "bad password" 
         Just pw -> lift $ putStrLn $ "Your password is " ++ pw 

우리가 시도-catch 블록과 같은 runMaybeT을 사용하고 있습니다 :

getPassphrase 당신의 MaybeT 버전을 사용하는 또 다른 방법은 runMaybeTaskPassphrase 실행을하는 것입니다.

+0

'askPassphrase'의 마지막 예제의'type'을 줄 수 있습니까? 두 버전 모두에 대해 동일한 기능의 이름에 사과드립니다. 나는 '1'과 '2'로 이름을 변경하지 않았습니다. 당신도 그것에 관해 당신의 대답을 바꿀 수 있습니까? –

+0

완료 - 마지막 코드 예제에서 오타가 수정되었습니다. – ErikR

+0

또한 - 그래서이 그래서 대답 도움이 될거야 : http://stackoverflow.com/a/32582127/866915 – ErikR