В базе нет такой вещи, но молодец, что задал мне самый интересный вопрос на Stack Overflow в течение некоторого времени.
Функторы и функторы Applicative закрываются при композиции (что, конечно, не относится к монадам в целом, поэтому необходимы преобразователи монад), поэтому liftA2.liftA2
работает здесь, а liftM2
обычно просто liftA2
, особенно теперь Applicative становится суперклассом. Монады.
Отступление:
Вы можете использовать композицию newtype в пакете Data.Functor.Compose составить аппликатив, но вы можете создавать новые аппликативы из старых и другими способами - я настоятельно рекомендую Gershom Сообщение Базермана «Абстрагирование с помощью аппликативов» в Comonad Reader для людей, которые хотят понять, насколько прекрасна комбинированная структура аппликативов по сравнению со стеком преобразователей монад - теперь я всегда ищу возможность делать вещи просто аппликативными, а не монадический, где я могу получить нужную мне функциональность. Часто я могу использовать Applicative, чтобы объединить все входные данные в значение, которое я хочу вывести, а затем направить его напрямую туда, где я собираюсь, используя >>=
.
Ваши функции и операторы
Конечно, ничто не мешает вам определять свои собственные функции:
liftliftA2 :: (Applicative f, Applicative g) =>
(a -> b -> c) -> f (g a) -> f (g b) -> f (g c)
liftliftA2 = liftA2.liftA2
но он ненамного короче liftA2.liftA2
.
Мне нравится ваша идея сделать вложенные операторы Applicative, но я переключусь на увеличение угловых скобок, а не на повторение внутреннего оператора, потому что <**>
конфликтует с (<**>) = flip (<*>)
в Control.Applicative, и это более логично.
import Control.Applicative
(<<$>>) :: (Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
(<<$>>) = fmap.fmap
(<<*>>) :: (Functor m, Applicative m, Applicative n) =>
m (n (a -> b)) -> m (n a) -> m (n b)
mnf <<*>> mna = (<*>) <$> mnf <*> mna
давая
ghci> (+) <<$>> [Just 5] <<*>> [Just 7,Just 10]
[Just 12,Just 15]
и, конечно, вы можете продолжать:
(<<<$>>>) :: (Functor f, Functor g, Functor h) =>
(a -> b) -> f (g (h a)) -> f (g (h b))
(<<<$>>>) = fmap.fmap.fmap
(<<<*>>>) :: (Functor l,Functor m, Applicative l, Applicative m, Applicative n) =>
l (m (n (a -> b))) -> l (m (n a)) -> l (m (n b))
lmnf <<<*>>> lmna = (<*>) <<$>> lmnf <<*>> lmna
Что позволяет сделать кажущееся невероятным
ghci> subtract <<<$>>> Right [Just 5,Nothing,Just 10] <<<*>>> Right [Just 100,Just 20]
Right [Just 95,Just 15,Nothing,Nothing,Just 90,Just 10]
но опять же, как демонстрирует статья Гершома Базермана, вы вполне можете захотеть вложить аппликативы так же глубоко, как вы, возможно, захотите вложить монады.
person
AndrewC
schedule
24.02.2015
myMonadicAdd = (liftM . liftM ) (+)
, поскольку использование вложенных монад будет специфичным для вашего приложения. - person ely   schedule 23.02.2015liftM . liftM
имеет тип, несовместимый с преобразователями монад, поэтому, если вам нужна эта функция очень, вам следует подумать о рефакторинге кода для использования преобразователя монад. Если этот конкретный пример является вашим фактическим вариантом использования, это может быть не очень хороший совет, потому чтоListT Maybe a
и[Maybe a]
- это не одно и то же. - person user2407038   schedule 23.02.2015ListT Maybe a
и обнаружил, что типы действительно не совпадают, что очень плохо. - person Lay González   schedule 23.02.2015(liftM . liftM) (+)
- ошибка типа, liftM2 нужен для (+) - person Lay González   schedule 23.02.2015fmap2
немного раздражает, на практике это так редко требуется и так легко определяется, что они не включили для него псевдоним. Вот сообщение в блоге, в котором обсуждается это: byorgey.wordpress .com / 2007/08/16 / mapping-over-a-nested-functor. - person danem   schedule 23.02.2015(+1)
, как в вашемliftM . liftM
примере. Было слишком поздно редактировать комментарий, когда я понял, что остановился на1
. Я не собирался использовать примерliftM2
. - person ely   schedule 23.02.2015liftM2.liftM2
работает, потому что в этих случаяхliftM2
=liftA2
и аппликативные функторы do составляют (в отличие от монад в целом). - person AndrewC   schedule 23.02.2015<$> == liftA
, есть ли операнд, скажем<$$>
, то<$$> == liftA.liftA
? - person Lay González   schedule 23.02.2015