Как избежать проверки пустого значения в Haskell?

Я пытаюсь понять, как программы на Haskell могут избежать проверки на «пустое значение». Я изо всех сил пытаюсь избавиться от выражения case в этой программе:

main =  do url:outputPath:[] <- getArgs
         let maybeUri = parseURI url
         case maybeUri of
              Just uri -> download uri outputPath
              Nothing -> return ()

Мое очень грубое понимание состоит в том, что я должен использовать монадный преобразователь, чтобы я мог использовать одно значение mappend для значения Maybe в монаде IO, и синтаксис 'do' должен поддерживать его. Как я могу этого добиться?


person Rumca    schedule 13.09.2013    source источник


Ответы (2)


Используйте forM_ из Data.Foldable, который имеет следующий тип:

forM_ :: (Monad m, Foldable t) => t a -> (a -> m b) -> m ()

Maybe реализует класс Foldable, ведя себя как список с нулем или одним элементом, поэтому, когда вы специфицируете t в приведенной выше сигнатуре типа на Maybe, вы получаете:

forM_ :: (Monad m) => Maybe a -> (a -> m b) -> m ()

Вы используете это так:

forM_ maybeUri $ \uri -> download uri outputPath

Он запустит действие только в том случае, если значение Maybe окажется Just.

person Gabriel Gonzalez    schedule 13.09.2013
comment
Или если downloadTo = flip download, то просто forM_ maybeUri $ downloadTo outputPath, что, на мой взгляд, читается намного приятнее. - person kqr; 14.09.2013
comment
@kqr Обычно, если я могу сократить аргумент, я переключаюсь на использование Data.Foldable.mapM_: mapM_ (downloadTo outputPath) maybeUri. - person Gabriel Gonzalez; 14.09.2013

Вы можете использовать Data.Maybe.maybe (он также есть в Prelude, поэтому импорт не требуется):

main = do
  url:outputPath:[] <- getArgs
  let maybeUri = parseURI url
  maybe (return ()) (\uri -> download uri outputPath) maybeUri
  -- The above can also be written as:
  -- maybe (return ()) ((flip download) outputPath) maybeUri

maybe занимает:

  • функция для запуска в случае Nothing: здесь, (return ())
  • функция для запуска значения внутри Just: здесь (\uri -> download uri outputPath)
  • значение Maybe: maybeUri

Я показываю альтернативный способ выражения функции для значения Just, используя частично примененную функцию.

Я бы поспорил за использование maybe, потому что это делает явным, без необходимости записывать выражение case, что вы имеете дело с Maybe.

person Yawar    schedule 17.09.2013