Haskell mapM vs forM взаимозаменяемо

Как я понимаю forM, это то же самое, что и mapM, только аргументы меняются на противоположные. Означает ли это, что я могу заменить каждый forM на mapM и наоборот, если просто изменить аргументы, которые я им даю?

Ответ 1

Действительно. forM буквально просто...

forM = flip mapM

... так что это за исключением порядка аргументов. Как стиль, forM выглядит красиво, когда аргумент функции представляет собой большой блок кода, который вы не удосужились дать имя, как в:

-- Somewhere in a do-block...
results <- forM items $ \item -> do
    -- A do-block using `item`.

Примечание: особенно если вы используете последнюю версию GHC (и, следовательно, версию пакета base версии 4.8), я предлагаю заменить mapM и forM на эквивалентные, но более общие traverse и for функций соответственно. Прелюдия в base-4.8 экспортирует traverse, в то время как вы можете найти for в Data.Traversable. Аналогично, Data.Foldable предлагает traverse_ и for_, которые являются более строгими, чем mapM_ и forM_.

Ответ 2

Да. Определение в base задается как

forM  = flip mapM

С помощью эквационального рассуждения Haskell это означает, что вы можете заменить forM на flip mapM, а затем заменить flip своим определением, чтобы получить нормальное видение mapM. Вы также можете выполнить этот процесс назад, чтобы перейти от mapM в forM.