Комментарии 51
Лучше ничего нет.
Уж лучше вообще ничего не объяснять, чем объяснять всё некой магией, которая дана нам свыше и с помощью божественной силы может "поднимать" монады и "преобразовывать" IO String
в String
. Нужно понимать как работает твой инструмент, на какую математику он опирается, во что преобразуется do нотация, что такое монады и зачем вообще они нужны, а не просто бездумно их использовать. Иначе чем это лучше Карго-культа?
К тому же в статье всё изложено бегло и скомкано, не приведено никаких примеров. Статья рассчитана на абсолютных новичков, однако изобилует сложными терминами. Половина кода в мыльных картинках, половина не подсвечена. Не знаю, к чему стремился автор, но желанием помочь новичкам он точно не горел.
Вот пример как нужно объяснять монады новичкам, не теряя при этом важных деталей, не используя сложных терминов и не скатываясь в объяснение через магическую силу.
Поэтому моя статья написана именно в таких терминах и именно на новичков она и рассчитана.
+1 к отсылке на видео (разве что я его смотрел на канале c9 от MS).
Причем фальшивые поддакивания и хмыканья человека за кадром только укрепляли данное впечатление.
Практические примеры нужны, практические.
А практические примеры — это совершенно другая сторона, чисто программистская и прикладная. Где монады применяются как способ композиции программы из частей, где части — это функции. И это по сути тоже весьма несложная штуковина, если математическую ее часть понимать на уровне того же Бекмана.
>Практические примеры нужны, практические.
На мой взгляд в этой статье примеры вполне себе практические. Я только не согласен, что они совсем-совсем для начинающих. Можно было и попроще придумать наверное.
Скажем, у вас есть функция, которая достает из базы какую-либо сущность. Дальше с ней нужно что-то сделать, некая последовательность обработки. При этом сущности в базе может и не быть.
Какие у нас есть варианты?
1. Проверяем после каждой функции «код возврата», который может нам говорить, что в базе ничего не нашли. Или была ошибка. Куча if в коде.
2. Выкидываем из функции поиска exception. Получаем типичный результат в стиле Java, который я приводить не буду, ибо их навалом.
3. Заворачиваем результат в Maybe. Дальше работаем с ним при помощи map/flatMap и т.п., так что вся последовательность пишется так, как будто у нас всегда есть результат.
Хотя на вкус и цвет, как говорится, все фломастеры разные, все же практическая польза тут обычно достаточно очевидна. Монады это, в частности, способ организации вычислений. В том числе — и в таких вот случаях. Который обеспечивает некоторые преимущества (и наверное, имеет некоторые недостатки), а именно более легко осуществляется композиция кода из частей.
Таких примеров — их в сети и так уже тысячи.
Мой простой ответ: это все ровно о том же. По крайней мере с точки зрения «снаружи от самой монады».
Самое нормальное объяснение, спасибо.
К стати, многие не знают, но optional, steam в java 8 — это монады. А еще есть rxjava...
Ну конечно есть различия. Если кому интересно вот тут подробнее: https://dzone.com/articles/whats-wrong-java-8-part-iii
Вернее вот тут: https://dzone.com/articles/whats-wrong-java-8-part-iv
Допустим, есть класс типов Monoid
class Monoid a where
mempty :: a
mappend :: a -> a -> a
Я могу «эмулировать» его в C# с помощью интерфейса
interface Monoid<A>
{
A mempty();
A mappend(A a1, A a2);
}
Затем я могу сделать instanse моноида для конкретного типа с помощью наследования
class IntMonoidInstance: Monoid<int>
{
int mempty(){ .. }
int mappend(int a1, int a2) { .. }
}
Но этот фокус не сработает для монады.
Класс типов монады объявлен как
class Monad m where
return :: a -> m a
(>>=) :: forall a b . m a -> (a -> m b) -> m b
Здесь m является не просто типом, как в случае с моноидом. Она является типом, параметризированным другим типом. Другими словами: * -> *.
Интерфейс для монады в C# должен выглядеть примерно так
interface Monad<M> where M: * -> *
{
M<A> return<A>();
M<B> bind<A, B>(M<A> a1, Func<A, M<B>> a2);
}
Но C# со своей мощной системой типов не позволяет делать такие штуки. Я не могу объявить интерфейс, параметризированный типом, который параметризирован другим типом.
Любые реализации монады в C# все равно останутся недо-монадой.
Это все-же не совсем так. Вы не можете сделать generic монаду, параметризованную. Это и для java кстати верно. Но любой конкретный экземпляр монады с фиксированными типами будет на практике вполне полноценным.
filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
Я вам больше скажу — в последние несколько лет это не просто популярно, это уже даже где-то модно.
jquery ($) это тоже монададокажите
И если вы поищете — то найдете тут аналогии для flatMap например. Причем легко.
Т.е. по сути, $ это полноценный функциональный вариант монады в ее программистском стиле (программистском — потому что есть еще строгое математическое определение монады в теории категорий).
Да, если строго подходить — то можно долго придираться, что для $ мы не можем доказать, что законы выполняются, что система типов языка не позволяет написать монаду раз и навсегда, как это выше описано на примере C#. Но фактически — это самая натуральная монада.
Не надо пороть гуманитарную чушь с умным видом. Монада — это мноноид в категории эндофункторов. Это на минутку ЕДИНСТВЕННОЕ ОПРЕДЕЛЕНИЕ монады. О том, каким образом класс типов Monad в Haskell представляет абстракцию этого ОПРЕДЕЛЕНИЯ, написано много и подробно. Вот и обоснуйте ваше утверждение про jQuery исходя из данного ОПРЕДЕЛЕНИЯ. Но вы не сможете, поскольку никакого отношения эта ваша жиквери к монадам не имеет, суть обычная обёртка над низкоуровневыми данными, по понятиям дурачка Фаулера — адаптер :)
Ок, докажите что ваш мир реальней, приведя "программисткое" определение и показав, что жиквери ему соответствует. Либо признайте, что ляпнули не подумав.
— Монада — термин в функциональных языках программирования.
— Монада — термин в теории категорий.
>Это на минутку ЕДИНСТВЕННОЕ ОПРЕДЕЛЕНИЕ монады.
Чё? Где-же единственное, когда вот их уже два (не считая еще трех, которые философского и прочих смыслов)? Вот идите, и сами себе доказывайте, что хотите.
Продолжаем гнать дурочку? :-) не прокатит.
В статье википедии, на которую вы ссылаетесь, никакого "программистского" определения монады к сожалению для вас нет, там про Monad из Haskell.Вы не удосужились прочесть материал прежде чем ссылаться на него, ограничившись заголовком. Если уж заикнулись про википедию, покажите, какое отношение имеет жиквери к материалу из этой статьи.
Извините, но это не я, а вы утверждали тут что жиквери — монада. Так что сперва обоснуйте своё утверждение ЛОГИЧЕСКИ (о доказательствах я уже молчу), а потом рассказывайте кому куда идти и что делать.
Может кому-то язык не родной?
«Мона́да в функциональном программировании — это абстракция линейной цепочки связанных вычислений. „
Итак, определение — не единственное. У меня уже все прокатило.
для $ мы не можем доказать, что законы выполняютсяесли так, $ не монада. для монад законы выполняются.
>Монады в программировании известны давно, но вне академических кругов не особо популярны на практике.
Суть моего замечания была в том, что соответствующие технологии и понятия (взятые из теории категорий, ясное дело) лежат в основе например $. То есть не просто популярны, а очень популярны. Вот в этом я и пытаюсь вас убедить.
>для $ мы не можем доказать, что законы выполняются
Я не просто верю, я практически знаю, что это так и есть. И что?
Начнем с того, что у $ весьма развесистое API, и тут нет прямого соответствия в виде «вот это bind, а вот это return». Более того, в языках типа javascript было бы глупо ожидать, что монада будет выглядеть как в хаскеле.
Ответьте, вот вам зачем монадические законы? На мой взгляд, они нужны исключительно для того, чтобы композиция работала правильно (а в идеале — чтобы это еще и статически проверялось). Но это далеко не всегда нужно, и далеко не всегда возможно (в конкретном языке).
Иными словами: если оно ходит как монада, крякает как монада, и плавает как монада — это монада и есть. Это такой вот прагматический подход, и именно таким образом монады уже давно и широко применяются налево и направо.
Ответьте, вот вам зачем монадические законы? На мой взгляд, они нужны исключительно для того, чтобы композиция работала правильно (а в идеале — чтобы это еще и статически проверялось). Но это далеко не всегда нужно, и далеко не всегда возможно (в конкретном языке).
Я просто поинтересовался причинами непопулярности монад. «это далеко не всегда нужно, и далеко не всегда возможно (в конкретном языке)» — вполне веский аргумент. Для композиции есть уйма других способов.
>Для композиции есть уйма других способов.
Ну да, есть. Но прям таки и уйма? Сможете назвать скажем четыре? )))
И потом, монады — один из достаточно удобных и проверенных.
далеко не всегда нужно формальное доказательство того, что законы монад соблюдаются. Это нам гарантирует правильность, но далеко не всю правильность, поэтому без этого вполне можно практически обходиться.тут вроде напрашивается другой вывод, что без соблюдения законов — которые гарантируют правильность, и то не всю — ни о какой правильности вообще не может быть и речи. $ это неправильный пример неправильной монады, так что-ли по-вашему?)
Ну да, есть. Но прям таки и уйма? Сможете назвать скажем четыре? )))https://en.wikipedia.org/wiki/Software_design_pattern
Ответьте, вот вам зачем монадические законы?
Выполнение монадических законов гарантирует, что вы вы получите то, что ожидаете при использовании монадических функций.
Не, вы конечно можете переопределить, что "+" это "-", но только при использовании "+" вас ожидают неожиданные результаты вычислений
Очень нехватало этой информации!
Haskell. Монады. Монадные трансформеры. Игра в типы