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

Взаимосвязь между Functor, Applicative Functor и Monad

При чтении в классах классов я видел, что взаимосвязь между Функторами, Аппликативными Функторами и Монадами - это строго возрастающая сила. Функторы - это типы, которые можно сопоставить. Аппликативные функторы могут делать то же самое с определенными эффектами. Монады одинаковы с возможным неограничивающим эффектом. Более того:

Every Monad is an Applicative Functor
Every Applicative Functor is a Functor

Определение Аппликативного функтора ясно показывает это:

class Functor f => Applicative f where
  pure  :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b

Но определение Монады:

class Monad m where
  return :: a -> m a
  (>>=)  :: m a -> (a -> m b) -> m b
  (>>)   :: m a -> m b -> m b
  m >> n = m >>= \_ -> n
  fail   :: String -> m a

По мнению Брент Йорги, большой typeclassopedia, что альтернативное определение монады может быть:

class Applicative m => Monad' m where
  (>>=) :: m a -> (a -> m b) -> m b

который, очевидно, проще и будет цементировать, что Functor < Аппликативный функтор < Монада. Так почему же это не определение? Я знаю, что аппликативные функции новы, но согласно Отчету Haskell 2010, страница 80, это не изменилось. Почему это?

4b9b3361

Ответ 1

Каждый хочет видеть, что Applicative становится суперклассом Monad, но он сломал бы столько кода (если return устранено, каждый текущий экземпляр Monad становится недействительным), который каждый хочет отложить, пока мы не сможем расширить язык в таких способ, который позволяет избежать нарушения кода (см. здесь для одного заметного предложения).

Haskell 2010 был консервативным, постепенным улучшением в целом, стандартизируя только несколько бесконтактных расширений и нарушая совместимость в одной области, чтобы привести стандарт в линии с каждой существующей реализацией. В самом деле, в библиотеках Haskell 2010 нет даже аппликативных - меньше того, что люди ожидали от стандартная библиотека стандартизована, чем можно было бы ожидать.

Мы надеемся, что ситуация скоро улучшится, но, к счастью, обычно это лишь незначительные неудобства (писать liftM вместо fmap в общий код и т.д.).

Ответ 2

Изменение определения Monad в этой точке могло бы повредить много существующего кода (любой фрагмент кода, который определяет экземпляр Monad).

Нарушение обратной совместимости, как это, стоит только, если есть большая практическая польза для изменения. В этом случае преимущество не настолько велико (и в основном теоретическое) и не будет оправдывать это количество разломов.