Подтвердить что ты не робот

Почему нет "альтернативного" экземпляра для "Control.Applicative.Const"

Существует экземпляр Monoid a => Monoid (Const a b) для Const functor из Control.Applicative. Существует также экземпляр Monoid m => Applicative (Const m).

Поэтому я ожидал, что есть также экземпляр Monoid m => Alternative (Const m), который совпадает с экземпляром для Monoid. Это просто упущение, которое должно быть исправлено, или есть более глубокая причина?

4b9b3361

Ответ 1

Я считаю, что есть более глубокая причина. Хотя кажется, что для Alternative нет канонического набора правил, для того чтобы Alternative имел смысл, определенно должно быть отношение между Alternative и его операциями Applicative (иначе это было бы просто произвольный моноид.)

Этот ответ в Confused значением класса типа 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).

См. также: