Почему аппликативная работа по умолчанию используется только для Maybe - PullRequest
0 голосов
/ 29 марта 2019

Я пытаюсь понять, почему аппликативные функторы работают по умолчанию (реализация не требуется) для некоторых функторов, таких как Maybe, а для других нет:

Пример:
Just (+3) <*> (Just 3) отлично работает "из коробки" -> 6
Left (+3) <*> Left 3 не работает
Just (+3) <*> Left 4 не работает, даже если я объявляю Either Int Int.

Я предполагаю, что в 99% случаев при работе с парами: (f (a->b) , f a) вы должны самостоятельно реализовать желаемое поведение ( декартово произведение (f (a->b)) X (f a)), и первый пример - это просто что-то простое из коробка.

Пример В случае (Maybe (a->b) , Either c d) нам нужно будет охватить все 4 случая:
Just - Left Just - Right Nothing - Left Nothing -Right

Я прав в этом предположении?

1 Ответ

7 голосов
/ 29 марта 2019

Экземпляр Applicative для Either определяется как:

instance Applicative (Either e) where ...

, учитывая тип (<*>), равен Applicative f => f (a -> b) -> f a -> f b для Either, то есть:

Either e (a -> b) -> Either e a -> Either e b

Тип Left равен e -> Either e a, поэтому тип Left (+3) равен

Num a => Either (a -> a) b

и тип Left 3:

Num a => Either a b

, который приводит к типу Left (+3) <*> Left 3 как (Num a, Num (a -> a)) => Either (a -> a) b, что вряд ли будет тем, что вы намеревались.

Поскольку это тип b, который содержит функцию и значение для работы, использование конструктора Right действительно работает:

Right (+3) <*> Right 3
=> Right 6
...