Я считаю, что есть более глубокая причина. Хотя кажется, что не существует канонического набора правил для Alternative
, чтобы Alternative
имело смысл, определенно должна быть связь между Alternative
и его Applicative
операциями (иначе это был бы просто произвольный моноид).
Этот ответ на Запутанный значением класса типов 'Alternative' и его связью с другими классами типов утверждает эти законы
- Правильная дистрибутивность (
<*>
): (f <|> g) <*> a = (f <*> a) <|> (g <*> a)
- Правильное поглощение (для
<*>
): empty <*> a = empty
- Распределение слева (из
fmap
): f <$> (a <|> b) = (f <$> a) <|> (f <$> b)
- Поглощение слева (для
fmap
): f <$> empty = empty
которые имеют для меня большой смысл. Грубо говоря, empty
и <|>
относятся к pure
и <$>
/<*>
так же, как 0 и + относятся к 1 и *.
Теперь, если мы добавим экземпляр Monoid m => Alternative (Const m)
, совпадающий с экземпляром для Monoid
/Applicative
, законы Права не будут выполняться.
Например, 2. не работает, потому что
empty <*> (Const x)
= Const mempty <*> Const x -- by the suggested definition of Alternative
= Const $ mempty `mappend` x -- by the definition of <*> for COnst
= Const x -- by monoid laws
который не равен empty = Const mempty
. Точно так же 1. терпит неудачу, простой контрпример - установка f = Const (Sum 1); g = Const (Sum 1) ; a = Const (Sum 1)
.
Смотрите также:
person
Petr
schedule
25.02.2015
Alternative
нет ничего глубокого. Как и в случае сMonadPlus
, никто не может даже договориться о том, какими должны быть его законы, а наиболее убедительным вариантом его использования является своего рода каламбур. Делайте с ним все, что хотите. - person dfeuer   schedule 23.02.2015