Для чего нужен Alt в экземпляре Monoid?

В экземплярах Monoid и Semigroup используется альтернативный Alt.

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

{-# LANGUAGE FlexibleInstances #-}
instance Alternative f => Semigroup (f a) where
  (<>) = <|>

instance Alternative f => Monoid (f a) where
  mempty = empty

И если мы можем написать это, можем ли мы тогда заменить Альтернативу на (Моноид (f a), Аппликативная f) в функциях?

Где вы нашли это определение? Я бы не ожидал, что это будет в стандартной библиотеке.

amalloy 20.11.2022 14:16

Я нахожу это там

N0lim 20.11.2022 14:57
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
2
2
99
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы используете (<|>) :: Альтернатива f => f a -> f a -> f a и пусто :: Альтернатива f => f a . Как следует из подписей, они определены для элементов типа Applicative f => f a. Таким образом, вы можете использовать эти функции только для обработки таких элементов, и, таким образом, если вы работаете с f a, например, для определения mempty :: f a с mempty = empty, то для этого требуется, чтобы f был членом Альтернативного класса типов.

При этом, хотя многие типы данных могут иметь экземпляры Semigroup и Monoid, определенные в зависимости от того, как реализован Alternative, это не лучший экземпляр сам по себе. Да, Alternative — это моноид для аппликативных функторов, но сам по себе он не должен быть экземпляром моноида для этих типов данных.

Ответ принят как подходящий

Вы используете его для получения Monoid для любого Alternative

{-# Language DerivingVia #-}

data F a = ..
  deriving (Semigroup, Monoid)
  via Alt F a

instance Functor     F where ..
instance Applicative F where ..
instance Alternative F where ..

Alt является новым типом по уважительной причине, поскольку существует множество способов описать Monoid поведение прикладного типа f a. Например Аппликативный лифтинг: Ап.

{-# Language DerivingVia #-}

data G a = ..
  deriving (Semigroup, Monoid, Num, Bounded)
  via Ap G a

instance Functor     G where ..
instance Applicative G where ..

Экземпляры, которые вы даете, максимально перекрываются, экземпляр Monoid любого применяемого типа теперь вынужден быть экземпляром Alternative, полностью игнорируя параметр a.

Есть много случаев, когда это было бы неправильно, например, Semigroup a => Semigroup (Maybe a) не совпадает с Semigroup, которое вы получили бы от Alternative Maybe.

Можно использовать довольно новую функцию QuantifiedConstraints для количественной оценки аргумента конструктора типа forall x. Monoid (f x). Это не то же самое, что Alternative, но похоже

{-# Language QuantifiedConstraints #-}
..

type Alternative' :: (Type -> Type) -> Constraint

class    (forall x. Monoid (f x)) => Alternative' f
instance (forall x. Monoid (f x)) => Alternative' f

Что с автономными экземплярами, такими как instance Functor F? Подразумевает ли DerivingVia как-то реализацию экземпляра?

amalloy 20.11.2022 14:28

Да, когда вы получаете через Alt F a, для этого требуются экземпляры Alternative FApplicative FFunctor F, а для Ap G a требуется Applicative G. Они означают написанные пользователем экземпляры, но интересная функция в последней базе (4.17) имеет возможность получать эти экземпляры для некоторых случаев:

Iceland_jack 20.11.2022 14:34

Если бы экземпляры, которые вы предлагаете, существовали в этой форме, каждый тип, соответствующий f a, немедленно подчинялся бы ей. Это включает в себя типы, где это имеет смысл, но учтите

newtype ResultsSum a = ResultsSum {funToSum :: a -> Int}

instance Semigroup (ResultsSum a) where
  ResultsSum p <> ResultsSum q = ResultsSum $ \x -> p x + q x

К сожалению, ResultsSum a соответствует f a. Но это не Alternative; это даже не функтор и не может им быть (скорее, это контравариант). Однако компилятор не принимает это во внимание при разрешении экземпляров: он просто видит два объявления экземпляров, оба заголовка которых предполагают, что ResultsSum является полугруппой, что вызывает ошибку неоднозначного экземпляра.

Конечно, этот пример можно решить с помощью прагм {-# OVERLAPPING #-}, но всегда лучше избегать перекрытий экземпляров, поскольку они могут привести к странным результатам. В этом нет необходимости, поскольку вы также можете получить эти экземпляры viaAlternative. Хотя лично я предпочел бы сделать наоборот: сначала определить экземпляр Monoid, а затем Alternative в его терминах.

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