Почему для Either нет альтернативного экземпляра, кроме полугруппы, которая ведет себя аналогично альтернативе?

Я новичок в Haskell, и мне интересно, почему нет альтернативного варианта Either но полугруппа, которая ведет себя так, как я ожидал бы от альтернативы:

instance Semigroup (Either a b) where
Left _ <> b = b
a      <> _ = a

Этот экземпляр отбрасывает или исправляет "ошибки", и когда оба операнда помечены как RightХватит первым. Разве это не тот "выбор", который предлагает альтернатива?

Я ожидаю, что экземпляр полугруппы будет выглядеть примерно так:

instance (Semigroup b) => Semigroup (Either a b) where
Left e  <> _       = Left e
_       <> Left e  = Left e
Right x <> Right y = Right (x <> y)

Это означает, что он распространяет ошибки и добавляет регулярные результаты.

Я полагаю, у меня неверное представление о Either или из вовлеченных типов классов.

2 ответа

Решение

Что бы вы ожидали Alternative экземпляр, чтобы дать вам. Я думаю, что это хороший способ почувствовать, как Alternative а также Semigroup отличается, чтобы посмотреть на другой тип, который имеет экземпляры для обоих: например, Maybe String:

λ > Just "a" <> Just "b"
Just "ab"
λ > Just "a" <> Nothing
Just "a"
λ > Nothing <> Just "b"
Just "b"
λ > Nothing <> Nothing
Nothing


λ > Just "a" <|> Just "b"
Just "a"
λ > Just "a" <|> Nothing
Just "a"
λ > Nothing <|> Just "b"
Just "b"
λ > Nothing <|> Nothing
Nothing

Хорошо, так что основное отличие, похоже, заключается в Just "a" а также Just "b", Это имеет смысл, поскольку вы объединяете их в случае Semigroup вместо того, чтобы принять левый смещенный вариант в случае Alternative,

Теперь, почему вы не могли иметь Alternative экземпляр для Either, Если вы посмотрите на функции, которые являются частью Alternative тип класса:

λ > :i Alternative
class Applicative f => Alternative (f :: * -> *) where
  empty :: f a
  (<|>) :: f a -> f a -> f a
  some :: f a -> f [a]
  many :: f a -> f [a]
  {-# MINIMAL empty, (<|>) #-}

Похоже, это определяет понятие empty; это личность (<|>) оператор. Идентичность в данном случае означает, что альтернативой между идентичностью и чем-то еще всегда является нечто иное.

Теперь, как бы вы создали личность для Either e a? Если вы посмотрите на ограничение на Alternative Например, вы можете видеть, что это требует f иметь Applicative пример. Все в порядке, Either имеет Applicative экземпляр объявлен для Either e, Как вы можете видеть Either является только аппликативным функтором для переменной второго типа (a в случае Either e a). Так тож для Either e потребуется e также иметь личность. Пока можно построить тип где e имеет экземпляр Alternative Вы не можете сделать пример для Alternative за Either с этим e потому что нет такого ограничения в определении класса типа (что-то вроде: (Alternative e, Applicative (f e)) => Alternative (f e)).

TL; DR: Мне жаль, если я потерял тебя из-за своего бессвязного, если коротко f в случае Either неправильный вид, Alternative требует f :: * -> * в то время как Either имеет вид Either :: * -> * -> *

Так Maybe может иметь экземпляр Alternative потому что это имеет вид Maybe : * -> * и имеет понятие идентичности (Nothing) что требуется empty, Посмотрите на все случаи Alternative и обратите внимание на тип каждого экземпляра типа данных.

Вы можете найти тип данных в ghci с помощью :k:

λ > :k Maybe
Maybe :: * -> *
λ > :k Either
Either :: * -> * -> *

За билет Дитриха Эппа, размещенный выше, проблема с Alternative является empty, Если у вас есть:

instance Alternative (Either a) where ...

Вы должны быть в состоянии извлечь некоторую ценность Either a b "из воздуха", который был вашим объектом идентичности. Одним из возможных примеров может быть:

instance (Monoid a)=> Alternative (Either a) where 
  empty = Left mempty
  ...

Вы также спрашиваете, почему Semigroup экземпляр определен так, как есть, и, честно говоря, я тоже не понимаю. Казалось бы, предлагаемый вами случай также разрешил бы (совместимый / законный) Monoid например,

instance Monoid b=> Monoid (Either a b) where
  mempty = Right mempty

И это будет соответствовать Maybe экземпляр (алгебраические отношения между Maybe и Either очевидны).

Так что ситуация не очень хорошая. Часть вопроса Alternative это своего рода класс второго класса, если хотите; это моноидальная вещь высшего рода, но ее отношение к Monoid а также Semigroupкоторый явно и явно (в документах) образует иерархию, не определен.

Я уверен, что в списке рассылки библиотек было много дискуссий, и если есть какие-то очевидные "правильные" решения, вполне вероятно, что переход к ним может привести (в худшем случае к молчанию) поломку.

Другие вопросы по тегам