Ответ 1
В бизнесе дизайна библиотеки мы сталкиваемся с выбором здесь, и мы решили быть менее чем полностью последовательными в нашей коллективной политике (или ее отсутствии).
Monoid
экземпляры для конструкторов типа Monad
(или Applicative
) могут возникать различными способами. Потоковый подъем всегда доступен, но мы не определяем
instance (Applicative f, Monoid x) => Monoid (f x) {- not really -} where
mempty = pure mempty
mappend fa fb = mappend <$> fa <*> fb
Заметим, что instance Monoid (a -> b)
является именно таким поточечным поднятием, поэтому поточечный подъем для (a -> m b)
происходит всякий раз, когда моноидный экземпляр для m b
делает поточечный подъем для моноида на b
.
Мы не делаем поточечного подъема в целом не только потому, что он предотвращал бы другие экземпляры Monoid
, носители которых были бы применимыми типами, но также потому, что структура f
часто считается более значительной, чем структура x
. Ключевым случаем является свободный моноид, более известный как [x]
, который является Monoid
на []
и (++)
, а не поточечным подъемом. Моноидальная структура исходит из обертывания списка, а не из обернутых элементов.
Мое предпочтительное эмпирическое правило действительно определяет приоритетность моноидальной структуры, присущей конструктору типа, либо поточечного подъема, либо моноидальной структуры конкретных экземпляров типа, как моноидный состав для a -> a
. Они могут и могут получить обертки newtype
.
Аргументы разрываются над тем, должен ли Monoid (m x)
совпадать с MonadPlus m
, когда оба существуют (и аналогично с Alternative
). Я считаю, что единственным хорошим экземпляром MonadPlus
является экземпляр экземпляра Monoid
, но другие отличаются. Тем не менее, библиотека несовместима в этом вопросе, особенно не в связи с тем (многие читатели увидели бы этот старый жучок на моем пути)...
... экземпляр monoid для Maybe
, который игнорирует тот факт, что мы обычно используем Maybe
для моделирования возможного сбоя и вместо этого наблюдаем, что для того, чтобы дать представление о типе данных о том, как вырезать дополнительный элемент, можно использовать полугруппа - нейтральный элемент, если она еще не имеет этого. Две конструкции порождают изоморфные типы, но они не являются концептуально родственными. (Изменить). Хуже того, идея выполняется неловко, предоставляя экземпляр ограничения Monoid
, когда требуется только Semigroup
. Я хотел бы видеть Semigroup
-extends- to-Monoid
реализована, но не для Maybe
.)
Возвращаясь к Kleisli
, в частности, у нас есть три очевидных экземпляра-кандидата:
-
Monoid (Kleisli m a a)
сreturn
и композицией Клейсли -
MonadPlus m => Monoid (Kleisli m a b)
поднятьmzero
иmplus
поточечно над->
-
Monoid b => Monoid (Kleisli m a b)
поднимая моноидную структуруb
надm
, тогда->
Я ожидаю, что выбор не был сделан, просто потому, что он не понял, какой выбор сделать. Я стесняюсь сказать это, но мой голос будет равен 2, указав приоритет структуры, исходящей от Kleisli m a
по структуре, исходящей от b
.