• монады Haskell Рассмотрим некое множество монадных трансформеров вида newtype T m a = T { runT :: m (SomeThing a) }. Допустим он имеет инстанс в MonadPlus, то есть для него есть такое mzero, что mzero >>= f = mzero и m >> mzero = mzero. Отличить это mzero от любого другого значения можно лишь по значению типа SomeThing a (про m мы ничего не знаем, а T вообще фикция), а что либо делать с ним я могу только в монаде m. Теперь предположим что m тоже MonadPlus. Предположим, что при связывание (val >> mzero) :: T m a (которое должно нам дать в итоге mzero :: T m a) внутри val находится mzero :: m (SomeThing a). Поскольку внутри инстанса бинда для трансформера вычисления происходят внутри монады m, то какова бы ни была логика связывания монады T, вместо этого мы передадим дальше mzero :: m (SomeThing a). Если каким-то чудом (а чудеса мы не рассмтриваем) не справедливо равенство T (mzero :: m (SomeThing a)) == mzero :: T m a, то для T не выполняется закон m >> mzero = mzero и он не MonadPlus. Как-то так.

Replies (9)

  • @ndtimofeev,
    Отличить это mzero от любого другого значения можно лишь по значению типа SomeThing a
    Что значит "по значению"? Оно же в монаде, там может не быть никакого значения.
  • @lomeo, mzero — это некое особое значение типа T m a. То есть теоретически, получив два значения этого типа мы можем сказать, что вот это mzero, а это — нет. Пока я ничего не перепутал?
  • @lomeo, Различить между собой два значения типа T m a, мы можем только по значению которое находится внутри монады m. А там как раз может внезапно выясниться что значения то никакого и нет, потому что это была скажем монада Maybe или List, связываться нам не с чем и вместо mzero для T мы получим mzero для m обёрнутый в T. То есть если mzero для трансформера нельзя определить паттерн-матчингом конструктора (а почти всегда так и есть), то делать его MonadPlus'ом нельзя. Во всяком случае получается пока так.
  • @ndtimofeev, Да, верно. А в чём пойнт поста?
  • @lomeo, В том что у многих трансформеров в transformers инстанс в MonadPlus есть. Сейчас в России модно писать про попранные законы. Вот, я тоже пишу.
  • @lomeo, Имеется в виду ListT, ErrorT, MaybeT. Насколько это справедливо для StateT я пока не думал. Можно наверное и ещё где-то поискать, но лень.
  • @ndtimofeev, StateT — не MonadPlus. А остальные вроде как нормально.
  • @lomeo, Prelude Control.Monad Control.Monad.Trans.State> :i MonadPlus
    class Monad m => MonadPlus m where
    mzero :: m a
    mplus :: m a -> m a -> m a
    — Defined in Control.Monad
    instance MonadPlus m => MonadPlus (StateT s m)
    — Defined in Control.Monad.Trans.State.Lazy
    instance MonadPlus [] — Defined in Control.Monad
    instance MonadPlus Maybe — Defined in Control.Monad
  • @ndtimofeev, О, не знал.