Здравствуйте, hi_octane, Вы писали:
_>Если бы это всё были монады а не разные захардкоженные сущности, то с точки зрения монад это всё абсолютно одно и тоже, с единым способом работы со всеми этими штуками. Нет никаких причин (и даже способов) различать во что обёрнуты значения, главное что это Monad<Int>. И если бы это было и для языка одним и тем же за счёт годного синтаксического сахара, т.е. если бы все переменные были монадами, то Dictionary<void, int> — это естественным образом получался бы List.
Не получится. У словаря нет порядка. У списка есть.
Далее есть множество и мультимножество. Они оба нужны. Но вот такой вот параметризацией из словаря их не получишь.
Если уж говорить об обобщении коллекций нужно начинать с чего-то типа этого
https://www.boost.org/doc/libs/1_67_0/libs/multi_index/doc/index.html
_>И в случае списка ты автоматом получишь последовательное или параллельное (в зависимости от деталей реализации обёртки) выполнение, а может даже распределённое или на GPU, а не как сейчас — ошибку типизации.
Баловство это. Если нужно что-то распараллелить, то нужно брать вот эту штуку или что-то похожее.
http://halide-lang.org/
_>Там всё очень алгебраично (для тех кто этот мем пропустил см. под катом)
_>
Неалгебраичный канал про математику.
https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw/videos?disable_polymer=1... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Здравствуйте, hi_octane, Вы писали:
_>Вот что в скале бесит (и наверное в хакселе, хоть я на нём и не пишу, но сорцы иногда читаю) — так это то что эта самая do-нотация нужна в явном виде. А в скале — так это запихнуто в for-comprehension, который спотыкается на простейших вещах (типа нормально иф в этот фор всунуть). Неужели нельзя добавить сахара в компилятор чтобы он распознавал код на монадах, и правильно его рассахаривал без do-нотации? Вроде задаче не сложнее чем та которую решает компилятор C# преобразуя функцию с async/await.
Альтернативой DO-нотации (то есть альтернативой нарезки кода на замыкания, пусть и автоматической) является call-with-current-continuation — среда выполнения в явном виде отдаёт нам всё необходимое для многократного продолжения с текущего места.
Это например позволяет оманадить код не меняя привычного синтаксиса. Вот
конкретный примерАвтор: Evgeny.Panasyuk
Дата: 16.01.14
.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Здравствуйте, WolfHound, Вы писали:
WH>Не получится. У словаря нет порядка. У списка есть.
У списка порядок подразумеваемый:
List<Value> === Dictionary<int, Value>
Доступ к элементам списка по индексу всё-равно ассоциативный.
WH>Далее есть множество и мультимножество. Они оба нужны.
WH>Но вот такой вот параметризацией из словаря их не получишь.
Dictionary<Key, List<Value>>
(если внутренее устройство не принципиально)
WH>Если уж говорить об обобщении коллекций нужно начинать с чего-то типа этого
WH>https://www.boost.org/doc/libs/1_67_0/libs/multi_index/doc/index.html
Это просто набор индексов над данными.
Вся фишка в хранении этих индексов — для не примитивных типов хранится не значение ключа, а ссылка на значение ключа в самих данных.
Но это опять тонкости реализации.
Здравствуйте, Maxim S. Shatskih, Вы писали:
MSS>Начинаю тему и приглашаю в нее тех, кто лучше меня в этом разбирается
Я плохо разбираюсь, но попробую свои 5 копеек вставить.
Начнем с того, что монада — это "паттерн" в понимании большинства программистов. Это не конструкция языка, хотя некоторые языки имеют конструкции, облегчающие использование монад.
Паттерн опирается паттерн на полиморфизм. В языках без полиморфизма монады не але.
Паттерн состоит из ЧЕТЫРЕХ элементов:
1) Полиморфный тип M<T>, тип обычно монадой и называют
2) Функция конструктор (
return) T->M<T>
3) Функция связывания (
bind) (M<T>, T->M<V>) -> M<V>
return и bind не произвольные, а должны подчиняться правилам:
— bind(return x, f) = f x
— bind(x, return) = x
Правило "монадного нуля"
— bind(bind(m,f), g) = bind(m, x -> bind(f(x), g))
Правило "ассоциативности bind"
4) Этот элемент отличает монадного теоретика от монадного практика.
Для практического использования монады нужна функция (
run) M<T> -> T
Возможно такая функция будет не одна.
MSS>Для каких именно практических нужд пригодны монады?
Практическая польза монад — иметь один набор более-менее понятных функций для работы с объектами разной природы.
1) flatten :: M<M<T>> -> M<T> = bind(m, x->x)
2) map :: (M<T>, T->V) -> M<V> = bind(m, x-> return f(x))
3) filter :: (M<T>, T-> Maybe<V>) -> M<V>. Увы, конкретная реализация зависит от M<T> и не всегда возможна.
4) merge :: (M<T>, M<V>) -> M<(T,V>) = bind(t, x -> bind(v, y -> return (x,y)))
5) join :: (M<T>, M<V>, (T,V) -> bool) -> M<(T,V>) = filter(merge(t,v), (x,y) -> if f(x,y) then Maybe(x,y) else None). Тоже от filter зависит.
итд (лень придумывать).
При наличии в языке полиморфизма второго порядка часть функций можно вынести в библиотеки.
Но самая главня фишка, которая уже должна броситься в глаза: везде на входе и выходе M<T>.
То есть код с монадой по большей части будет выглядеть так:
bind(bind(bind(x,f),g),h)
Ни проверок, ни try\catch в таком коде не нужно. Вся "грязь" перемещается в run.
Вся сложность "инкапсулируется" в функциях f,g,h, что очень в духе Функционального Программирования.
Программистам надо писать функции типа T->M<V> и не особо думать о композиции функций. За счет частичного применения T->M<V> может иметь любое количество агрументов перед T.
Это довольно сильное преимущество, если вместо абстрактного M<T> подставить List, Maybe, Try, Parser, Future, Writer и IO монады.
MSS>и что называется монадой в языках, отличных от Хаскеля?
В других языках монадой называется все то же самое.
Но, как уже заметили, код с кучей вложенных bind смотрится криво.
Поэтому в языках, где bind записывается инфиксно (
x `bind` f) монады оказываются гораздо красивее.
В хаскеле это оператор >>=, в C# это query comprehension.
Также в хаскеле есть особенность — run функция для IO встроена в рантайм.
MSS>Получается старый добрый декоратор который можно реализовать в обычных ОО языках наследованием с перекрытием пабликов.
Можно и декоратором назвать, главное bind реализовать правильно.
Об этом не пишут в книгах и статьях.
Монады появляются с появления функции run.
Вы видите функцию с сигнатурой M<T> -> T или сводимую к ней путем частичного применения.
Вы задумываетесь: можно ли к типу M<T> придумать функции bind и return такие, чтобы удовлетворять монадным правилам.
Если такие функции придумываются, то поздравляю, у вас монада.
Здравствуйте, Maxim S. Shatskih, Вы писали:
MSS>Для каких именно практических нужд пригодны монады? и что называется монадой в языках, отличных от Хаскеля?
Вообще говоря, я понимаю монаду как хрень, для которой определены операции bind (то есть преобразовать объект в монаду) и flatMap, преобразующую эту монаду в последовательность других монад. Монады удобны тем, что позволяют выстраивать цепочки из нетривиальной логики достаточно элегантно. Например описывать цепочки асинхронных запросов, каллбек одного является параметром для следующего. Вместе с прокидыванием ошибок, вместе с обработки null и т.д. Основная выгода от них — они позволяют избавиться от кучи if, код в принципе выглядит стройнее, логичнее и короче. Минусы тоже есть — читаемость монад оставляет желать лучшего, понять что конкретно и как делается далеко не всегда тривиально, приходится напрягать мозги. Соответственно для многих вещей они весьма полезны. Но если можно обойтись без них, и некоторые вещи поддерживаются языком (например не Nullable типы позволяют обойтись без Maybe зачастую, функционал async await в языке позволяет строить цепочки асинхронных вызовов гораздо более читаемо, чем с помощью монад).
Соответственно для многих задач является если не панацеей, то наименьшим злом. Главное не увлекаться, во всем должно быть чувство меры.
Здравствуйте, elmal, Вы писали:
E>Вообще говоря, я понимаю монаду как хрень, для которой определены операции bind (то есть преобразовать объект в монаду) и flatMap, преобразующую эту монаду в последовательность других монад. [..]
Монада — очень простая абстракция, но как почти любая абстракция, она может быть сложной для понимания. Это же математика, просто запрограммированная, а в программировании математики остается все меньше и меньше... Вон, люди тоже не сразу поняли, что можно придумать ноль, которого как бы и нет в природе, но он оказался очень полезным. Монады тоже полезны, для того же имитационного моделирования, например.
Есть простой способ разобраться с монадами — начать изучать общецелевой язык программирования Haskell, например, по вышедшей в этом году книге "Get Programming with Haskell":
https://www.manning.com/books/get-programming-with-haskell