2016-08-08 7 views
4

Я пытаюсь прочитать информацию, введенную пользователем, и проанализировать ее на тип Person, который использует тип Gender. Для этого я использую этот код:MaybeT/Maybe and IO: Отказоустойчивое чтение информации

data Person = Person String Int Gender String 
data Gender = Male | Female | NotSpecified deriving Read 

instance Show Gender where 
    show Male = "male" 
    show Female = "female" 
    show NotSpecified = "not specified" 

instance Show Person where 
    show (Person n a g j) = "Person {name: " ++ n ++ ", age: " ++ show a ++ 
     ", gender: " ++ show g ++ ", job: " ++ j ++ "}" 

readPersonMaybeT :: MaybeT IO() 
readPersonMaybeT = do 
    putStrLn "Name?:" 
    name <- getLine 
    putStrLn "Age?:" 
    ageStr <- getLine 
    putStrLn "Gender?:" 
    genderStr <- getLine 
    putStrLn "Job?:" 
    job <- getLine 

    let newPerson = Person name (read ageStr) (read genderStr) job 
    putStrLn $ show newPerson 

Теперь я хотел бы сделать это более отказоустойчивые - для достижения этой цели я пытался использовать MaybeT монады. с помощью этого, я получил этот код:

readPersonMaybeT :: MaybeT IO() 
readPersonMaybeT = do 
    lift $ putStrLn "Name?:" 
    name <- lift getLine 
    lift $ putStrLn "Age?:" 
    ageStr <- lift getLine 
    lift $ putStrLn "Gender?:" 
    genderStr <- lift getLine 
    lift $ putStrLn "Job?:" 
    job <- lift getLine 

    let newPerson = Person name (read ageStr) (read genderStr) job 
    lift $ putStrLn "show newPerson" 

It получить компилирует /, нагруженного GHCI, но когда я пытаюсь выполнить функцию readPersonMaybeT Я получаю сообщения об ошибке

Нет экземпляра для (Data .Functor.Classes.Show1 IO) , возникающие при использовании `печати» в виде зЬтЬ интерактивной команды GHCi: распечатать его

Как я могу решить эту проблему? Написав этот код, я использовал wikibook о Monad Transformers.

EDIT: Когда я пытаюсь «запустить» его с runMaybeT, он запускается, но он не является безотказным вообще. Ввод бессмыслицы для возраста, например, все еще приводит к результату, например

Лицо {имя: 85, возраст: *** Исключение: Prelude.read: нет синтаксического разбора.

+0

Как вы его выполнили? Вы использовали ['runMaybeT'] (http://hackage.haskell.org/package/transformers-0.5.2.0/docs/src/Control.Monad.Trans.Maybe.html#runMaybeT)? – pdexter

+0

Нет, я не знал, что мне нужно вызвать runMaybeT ... Но я попробовал это сейчас, и это не решило настоящую проблему (см. EDIT). – FlashTek

+0

вы должны показать нам определение 'Person' – ErikR

ответ

5

Если вы делаете проверку только после того, как вы попросили для всех входных данных, я бы просто использовать монады IO и возвращает Maybe:

import Text.Read 
import Control.Monad.Trans.Maybe 
import Control.Monad.IO.Class 

askPerson :: IO (Maybe Person) 
askPerson = do 
    name <- putStr "Name? " >> getLine 
    a <- putStr "Age? " >> getLine 
    g <- putStr "Gender? " >> getLine 
    return $ do age <- readMaybe a 
       gender <- readMaybe g 
       return $ Person name age gender 

Обратите внимание, как мы используем Может монада в заявлении return.

Я хотел бы использовать MaybeT, если вы хотите бросить задаёте, когда они ввести недопустимое значение -

askPersonT :: MaybeT IO Person 
askPersonT = do 
    name <- liftIO $ putStr "Name? " >> getLine 
    age <- MaybeT $ fmap readMaybe $ putStr "Age? " >> getLine 
    gender <- MaybeT $ fmap readMaybe $ putStr "Gender? " >> getLine 
    return $ Person name age gender 

doit = runMaybeT askPersonT 

Если пользователь вводит неверный возраст не будет предложено для пола.

+1

Во-первых, 'return (Person <$> чистое имя <*> readMaybe a <*> readMaybe g)' также идиоматично, я думаю. Во втором мы также можем использовать аппликативный стиль, но я на самом деле предпочитаю его, как вы его написали, поскольку каждая строка уже нетривиальна. – chi

+0

Чистый в вашем комментарии меня смущает. Разве мы не находимся в правильном контексте из usr возврата и fmap? – amalloy

+0

О, я понял. Я пропустил, что происходит с вызовами readMaybe. – amalloy

 Смежные вопросы

  • Нет связанных вопросов^_^