Ответ 1
Первое, что нужно помнить, это немного сложнее, чем это должно быть - любой экземпляр Monad
должен иметь связанный экземпляр Applicative
, так что функции liftM
и liftA
совпадают. Таким образом, здесь два руководства:
-
Если вы пишете общую функцию для любого
Monad
, используйтеliftM
& co. чтобы избежать несовместимости с другими функциями, которые имеют только ограничениеMonad
. -
Если вы работаете с конкретным экземпляром
Monad
, который, как вы знаете, имеет сопровождающий экземплярApplicative
, используйте операторыApplicative
последовательно для любого определения или подвыражения, где вам не нужны операцииMonad
, но не смешивайте их бесцельно.
Должен ли я использовать
Applicative
, чтобы подчеркнуть, что делает код, или я должен использоватьMonad
, потому что он может (?) иметь оптимизации по сравнению сApplicative
?
В общем, если есть разница, это будет наоборот. Applicative
поддерживает только статическую "структуру" вычисления, тогда как Monad
разрешает встроенный поток управления. Рассмотрим списки, например - с помощью Applicative
, все, что вы можете сделать, это сгенерировать все возможные комбинации и преобразовать каждый из них - количество элементов результата определяется полностью количеством элементов на каждом входе. С помощью Monad
вы можете создавать разные количества элементов на каждом шаге на основе элементов ввода, позволяя вам произвольно фильтровать или расширять.
Более ярким примером является экземпляр Applicative
и Monad
на основе бесконечных потоков zipping - Applicative
может просто закрепить их вместе очевидным образом, тогда как Monad
должен пересчитать множество вещей, которые он затем отбрасывает.
Итак, последняя проблема - liftA2 f x y
vs. f <$> x <*> y
или эквиваленты Monad
. Мой совет здесь был бы следующими рекомендациями:
- Если вы все равно пишете любой аргумент, используйте форму infix, потому что ее легче читать для больших выражений.
- Если вы просто снимаете существующую функцию, используйте
foo = liftA2 bar
, а неfoo x y = bar <$> x <*> y
- она короче и более четко выражает то, что вы делаете.
И, наконец, по вопросу о непротиворечивости нет причин, по которым вы не могли бы просто определить свой собственный liftA4
и т.д., если они вам понадобятся.