Я играл с компонуемыми ошибками и мне удалось написать функцию с сигнатурой
getPerson :: IO (Maybe Person)
, где Person есть:
data Person = Person String Int deriving Show
Это работает, и я написал ее в do-нотация, как показано ниже:
import Control.Applicative
getPerson = do
name <- getLine -- step 1
age <- getInt -- step 2
return $ Just Person <*> Just name <*> age
где
getInt :: IO (Maybe Int)
getInt = do
n <- fmap reads getLine :: IO [(Int,String)]
case n of
((x,""):[]) -> return (Just x)
_ -> return Nothing
Я написал эту функцию с целью создания возможных возможных отказов. Хотя у меня мало опыта работы с монадами, кроме Maybe и IO, похоже, что если бы у меня был более сложный тип данных с большим количеством полей, цепные вычисления не были бы сложными.
Мой вопрос в том, как бы я переписал это без do -отчет? Поскольку я не могу связать значения с такими именами, как имя или возраст, я не совсем уверен, с чего начать.
Причина вопроса - просто улучшить мое понимание (>> =) и (<*>) и составления неудачи и успехи (чтобы не загадывать мой код неразборчивыми однострочниками).
Edit: Думаю, мне следует пояснить, «как мне переписать getPerson без do-notation», меня наполовину не волнует функция getInt.