Как мне написать следующую функцию с помощью оператора >>=

#haskell #monads

#haskell #монады

Вопрос:

Как мне написать эту функцию с помощью оператора >>=?

 parseNumber2 :: Parser LispVal
parseNumber2 = do x <- many1 digit
                  return $ (Number . read) x
  

Ответ №1:

Простое удаление обозначения do дает

 parseNumber2 :: Parser LispVal
parseNumber2 = many1 digit >>= (return . Number . read)
  

но более идиоматичным способом является использование fmap или эквивалентного <$> оператора из Control.Applicative

 parseNumber2 = Number . read <$> many1 digit
  

Для десугаризации do-нотации:

  1. Переверните любые <- привязки на правую сторону и добавьте >>= абстракцию lambda

     do x <- a
       y <- b
       ...
      

    становится

     a >>= x ->
    b >>= y ->
    ...
      
  2. Для любых необязательных форм добавьте >> справа:

     do a
       b
       ...
      

    становится

     a >>
    b >>
    ...
      
  3. Оставьте последнее выражение в покое.

     do a
      

    становится

     a
      

Применяя эти правила к вашему коду, мы получаем

 parseNumber2 =
    many1 digit >>= x -> 
    return $ (Number . read) x
  

Сделайте некоторые упрощения

 parseNumber2 = many1 digit >>= x -> (return . Number . read) x
parsenumber2 = many1 digit >>= (return . Number . read)
  

Теперь для любой монады fmap или <$> может быть определено как

 f <$> x = x >>= (return . f)
  

Используйте это, чтобы получить идиоматическую форму

 parseNumber2 = Number . read <$> many1 digit
  

Комментарии:

1. Смотрите также RWH # Удаление блоков do и Haskell 2010 > Выражения # Do