Здравствуйте, AndrewVK, Вы писали:
AVK>>>И при чем тут LINQ? SelectMany это просто статический метод в классе Sequence. То что он extension method, это просто синтаксический сахар.
L>>Не понял претензии... А bind это просто метод в классе Monad.
AVK>И что? Как это доказывает утверждение о сходстве LInQ и монад?
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, BulatZiganshin, Вы писали:
BZ>>я и написал, что у нас есть два метода — либо всюду тащить это как параметр, либо сделать глобальным сервисом/переменной/whatever. фишка в том, что разные вычисления (например, разные треды) могут использовать два разных логгера. или парсить/генерить две разных программы. или вести сериализацию в два разных участка памяти. и тут ты натыкаешься на глобальные переменные в том или ином виде со всеми вытекающими последствиями.
AVK>Я наверное плохо объясняю. Вот описание Фаулера — http://www.martinfowler.com/articles/injection.html#ADynamicServiceLocator . Этот паттерн не является никоим разом аналогом глобальной переменной и проблем по смене инстанса сервиса на любом уровне нет никаких.
разве? вот представьте себе, что вы хотите сериализовать сложный составной объект. первый раз — в строку, второй — в сетевой порт. в хаскеле вы пишете что-то типа:
str <- serializeToStr h (put x)
serializeToFile h (put x)
и все объекты, вложенные в x, выполняя обычную операцию put, будут лить данные туда, куда им указали. с этим же паттерном, как я понимаю, надо настраивать этот сервис в *каждом* из сериализуемых объектов, входящих в x
что-то я не понимаю. если два треда одновременно будут сериализовать одну структуру в разные места, то тут как раз и проявится то, что это сервис является аналогом глобальной переменной, верно?
Здравствуйте, BulatZiganshin, Вы писали:
BZ>что-то я не понимаю. если два треда одновременно будут сериализовать одну структуру в разные места, то тут как раз и проявится то, что это сервис является аналогом глобальной переменной, верно?
Это если экземпляр сервиса будет один. А если будут разные экземпляры на поток?
Здравствуйте, VladD2, Вы писали:
VD>Фатк же остается фактом. Монада не имеет смысла в императивном языке. В C# есть объекты. У объектов есть состояние которое можно менять как угодно. Такое изменение будет всегда совершенно последовательным. Так что в ООП монада — это идиотизм.
А вот тут влезу я
В целом мысль которую я буду излагать где-то уже говорил lomeo, но что-то не могу найти сходу.
Монады имеют точно такой же смысл как любой интерфейс.
Точно такой же, как IEnumerable или IList. Только интерфейс называется IMonad.
Аналогия. Представь себе язык без массивов. Вообще. Только списки. И есть набор списков реализующих IList. Допустим List, Queue, Dictionary. А какой-то умник при помощи этого IList умудрился сэмулировать Array. То есть в языке как таковом массивов нет, но мы их эмулируем используя всем известный интерфейс.
Понятное дело что для языков, в которых массивы были отродясь Array реализованный через IList выглядит по меньшей мере извращением и мозго.. в общем brainfuck-ом. Но это не значит что сама идея интерфейса IList ущербна, и что классы List, Queue, Dictionary не нужны в языке поддерживающием массивы.
Монада это интерфейс. КАК его использовать — личное дело каждого. И какие классы будут реализовывать этот интерфес в целом неважно. Важно то, что они будут иметь унифицированный интерфейс.
LCR>То есть я хочу сказать, что автоматически переносить понятие функции из математики в программирование может быть просто непрактично.
LCR>Вот теперь я вернусь обратно. Предположим, я ввожу соглашение (примерно то, что Влад предлагает): функции, которые в реализации используют нечистые конструкции, по соглашению будут начинаться с подчёркивания. Но чтобы избежать транзитивного замыкания грязи, мы вне таких функций будем пользоваться нашими старыми знакомыми — монадами: LCR>
LCR>_solve :: Matrix Int -> Vector Int -> Vector Int
LCR>_solve m b = -- далее идёт метод решения СЛАУ с матрицей m и правым столбцом b скажем методом LU
LCR> -- разложения, здесь можно использовать традиционный доступ к мутабельным массивам,
LCR> -- циклы и т.п.
LCR> -- компилятор рассматривает эту функцию как неделимую сущность
LCR>main :: IO () -> ()
LCR>main = do
LCR> (m, b) <- loadSLAE("slae.txt")
LCR> putStrLn (show $ _solve m b)
LCR>
LCR>Таким образом мы можем устранить все критичные участки, что с _практической_ точки зрения благо. Разумеется, этот метод должен применяться только в качестве последнего средства (после ! и seq).
LCR>И что самое интересное, подобная возможность уже в Хаскеле есть — это FFI. Вот мне любопытно, что такого плохого станется, если поднять императив на уровень языка и использовать его в ограниченном контексте? Это несколько некомфортно с идеологической точки зрения, но практически полезно.
честно говоря непонятно, что конкретно ты предлагаешь. в хаскеле и так уже есть чистые функции и, назовём их так, "процедуры". последние работают в IO monad. далее, функция не может вызывать процедуру, всё остальное возможно. таким образом, транзитивное замыкание приводит к тому, что внутри чистого кода может выззываться только чистый код (с поправкой на ST и тому подобные монады), а внутри императвиного — вс что угодно
на уровне языка "процедуры" имеют тип (... -> IO a). в "IO Inside" описано как механизм типов делает невозможным выщов процедур из функций (окромя испольщования unsafePerformIO)
может, ты предлагаешь ST Monad?
f :: Int -> Int
f a = runST (do x <- newSTRef a
modifySTRef x (*2)
readIORef x
)
"f 2" возвратит 4, при этом f остаётся чистой функцией
есть в ST монаде и массивы, собственно она и есть сестра IO monad с набором операций, ограниченным работой с mutable variables and arrays. при этом код работает с той же скоростью, что и в IO монаде (или имерпативном языке), разница между ними чисто на уровне type tricks
(я даже сделал в одной своей библиотеке обощённый класс, который позволяет писать monadic code, и затем исполнять его в контексте хоть IO monad, хоть ST monad. очень удобно для реализации той же библиотеки сериализации — один и тот же код в ней может работать как IO объектами типа файлов, так и с pure объектами типа строк — http://haskell.org/haskellwiki/Library/ArrayRef)
BZ>>что-то я не понимаю. если два треда одновременно будут сериализовать одну структуру в разные места, то тут как раз и проявится то, что это сервис является аналогом глобальной переменной, верно?
AVK>Это если экземпляр сервиса будет один. А если будут разные экземпляры на поток?
это и есть global state на уровне треда. недостатки — не сможет справиться с ситуацией, когда работают несколько объектов, которым нужны разные контексты (в случае использования continuations, lazy evaluation), нет статической проверки того, что используются только включённые в данный момент интерфейсы. но по большому счёту это вполне терпимый вариант и я не сомневаюсь, что либо через thread-local state, либо через параметры это всегда и реализуется
Здравствуйте, BulatZiganshin, Вы писали:
BZ>это и есть global state на уровне треда.
Только в случае, если сервис опубликован в корневом сервис-менеджере. А если не в корневом, то только в пределах его контекста. А дальше все уже зависит от конкретного приложения. Монады тут ничего не меняют, бо проблема логическая, а не технологическая.
BZ>>это и есть global state на уровне треда.
AVK>Только в случае, если сервис опубликован в корневом сервис-менеджере. А если не в корневом, то только в пределах его контекста. А дальше все уже зависит от конкретного приложения. Монады тут ничего не меняют, бо проблема логическая, а не технологическая.
монады — это (в данном случая) механизм неявной передачи параметра во все процедуры, вызываемые из данной. т.е. если мы написали, что во всех выхзовах внутри вот этого делать логгинг в один файл, а во всех вызовах внутри этого делать логгинг в другой, то так оно и будет работать
вообще, мне кажется, что вы с этими паттернами за деревььями не видите леса. как это не обзови и в какие объекты не заверни, это thread-local state, не больше и не меньше. монады, как их не обхови — в данном случае просто способ передать параметр во все нужные вызовы. thread-local state проблему на 100% не решает, параметры же — решают, и при наличии такого средства в языке все эти дополниьтельные параметры совершенно не усложняют структуру программы
Здравствуйте, BulatZiganshin, Вы писали:
BZ>вообще, мне кажется, что вы с этими паттернами за деревььями не видите леса.
С чего ты сделал такой вывод? Или у тебя такая реакция на слово паттерн?
BZ> как это не обзови и в какие объекты не заверни, это thread-local state, не больше и не меньше. монады, как их не обхови — в данном случае просто способ передать параметр во все нужные вызовы. thread-local state проблему на 100% не решает, параметры же — решают, и при наличии такого средства в языке все эти дополниьтельные параметры совершенно не усложняют структуру программы
Так ты ничего и не понял. Умываю руки, объяснить что такое service locator я, видимо, не в состоянии
BZ>>вообще, мне кажется, что вы с этими паттернами за деревььями не видите леса.
AVK>С чего ты сделал такой вывод? Или у тебя такая реакция на слово паттерн?
потому, что я я сказанное тобой понял именно как сслыку на thread-local state
BZ>> как это не обзови и в какие объекты не заверни, это thread-local state, не больше и не меньше. монады, как их не обхови — в данном случае просто способ передать параметр во все нужные вызовы. thread-local state проблему на 100% не решает, параметры же — решают, и при наличии такого средства в языке все эти дополниьтельные параметры совершенно не усложняют структуру программы
AVK>Так ты ничего и не понял. Умываю руки, объяснить что такое service locator я, видимо, не в состоянии
а что я из этого мог понять: "Только в случае, если сервис опубликован в корневом сервис-менеджере. А если не в корневом, то только в пределах его контекста. А дальше все уже зависит от конкретного приложения. " ?
объясни, где всё же прячутся эти данные. я вижу три варианта — объекты, параметры, global state
Здравствуйте, BulatZiganshin, Вы писали:
AVK>>С чего ты сделал такой вывод? Или у тебя такая реакция на слово паттерн?
BZ>потому, что я я сказанное тобой понял именно как сслыку на thread-local state
Вот поэтому я и умываю руки.
BZ>объясни, где всё же прячутся эти данные. я вижу три варианта — объекты, параметры, global state
AndrewVK wrote: > > Контекст еще есть. И не обязательно это TLS.
Каким образом этот контекст попадает в точку вызова сервиса? Я
пробежался по описанию Фаулера, но сути не уловил. Ну, есть синглтон с
хэш-таблицей именованных объектов-сервисов (их еще и кастить надо,
тьфу), дальше что? Кто и как обеспечивает деление на уровни и доставку
контекста, в двух словах?
Здравствуйте, palm mute, Вы писали:
>> Контекст еще есть. И не обязательно это TLS. PM>Каким образом этот контекст попадает в точку вызова сервиса?
Передается в параметрах метода или параметрах конструктора например. Зависит от конкретной архитектуры конкретной системы.
PM>Я PM>пробежался по описанию Фаулера, но сути не уловил.
Да, к сожалению более доходчивых описаний я в инете не видел.
PM> Ну, есть синглтон
Синглтон это как раз не очень правильно.
PM>с PM>хэш-таблицей именованных объектов-сервисов (их еще и кастить надо, PM>тьфу)
Чтобы не кастить есть дженерики
PM>, дальше что? Кто и как обеспечивает деление на уровни и доставку PM>контекста, в двух словах?
Деление на уровни обеспечивается архитектором системы. Про контекст я написал выше.
AndrewVK wrote: > > >> > Контекст еще есть. И не обязательно это TLS. > PM>Каким образом этот контекст попадает в точку вызова сервиса? > > Передается в параметрах метода или параметрах конструктора например. > Зависит от конкретной архитектуры конкретной системы.
Так об этом же и говорил Булат. С помощью монад можно избавиться от
передачи в аргументах метода или конструктора.
Здравствуйте, palm mute, Вы писали:
PM>Так об этом же и говорил Булат. С помощью монад можно избавиться от PM>передачи в аргументах метода или конструктора.
Да не избавляется он, просто скрывает так или иначе. Да и не нужно от этого избавляться. Одно дело, когда нужно каждый сервис протаптывать руками, а другое, когда контекст передается во все объекты один раз, потому что это заложено в архитектуру системы. Опять же контекст полезен сам по себе, безотносительно сервисов.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, palm mute, Вы писали:
PM>>Так об этом же и говорил Булат. С помощью монад можно избавиться от PM>>передачи в аргументах метода или конструктора.
AVK>Да не избавляется он, просто скрывает так или иначе. Да и не нужно от этого избавляться. Одно дело, когда нужно каждый сервис протаптывать руками, а другое, когда контекст передается во все объекты один раз, потому что это заложено в архитектуру системы. Опять же контекст полезен сам по себе, безотносительно сервисов.
это вы рассужаете о своём паттерне. в моём примере использования монад речь шла о другом. есть универсальная процедура сериализации. куда сериализировать — она узнаёт из контекста вызова, т.е. из тех самых параметров. монады позволяют передавать эти паораметры неявно на всю глубину вызовов
ну а назвать serialization target сервисом и потом говорить, что это часть арзитектуры системы, за которую никак не меньше чем архитектор отвечает — это как раз попытка натянуть какой-нибудь из знакомых паттернов туда, где он похож на нужное только отдалённо
монады как раз повзоляют запрограммировать такое раз и навсегда и не запихивать что попало в арзитектуру системы, не говоря уж о прочих перечисленных мной (хотя и не очень значительных) преимуществах
Здравствуйте, GlebZ, Вы писали:
GZ>Все таки стоит различать монаду как математический термин, и монаду как реализацию в функц. языка(там указано именно теоретические идеи). Это не есть совсем одно и то же, хотя и близкие понятия. Если брать функц. языки, то в данном случае как аналог исчисления монад больше подходит list comprehension. Да и во многом, если говорить именно о Linq, надо вообще говорить о monoid calculus.
Твоя точка зрения не противоречит моей и в общем дополняет её, но с тобой Влад не спорит
now playing: Noisia & Phace — Outsource (Misanthrop Remix)
Здравствуйте, BulatZiganshin, Вы писали:
BZ>во-первых, там просто нет блоков кода. описания в чисто математическом ключе:
BZ>
BZ>f x = let y = x*2
BZ> z = y+3
BZ> in y*z
BZ>
Это и есть блок кода если не уверять себя, что "ложки нет".
BZ>т.е. вставить в такой набор мат. равенств вызовы процедур довольно проблематично.
В других языках (не помешанных на чистоте) получается.
BZ> во-вторых, это потребовало бы больших переделок в языке и компиляторах, поскольку нарушило бы чистоту языка и независимость результата от порядка вычислений. т.е.
Это потребовало бы иного дизайна языка.
BZ> пришлось бы вводить спец. правила взаимодействия императивного и чистого кода.
В других языках это удается. И правил особых не надо.
BZ> фактически это и было сделано, но не на уровне изменения описания языка, а на уровне описания всех необходимых изменений средствами самого хаскела. и этот realWorld — это как раз и есть описание семантики императивных вычислений средствами семантики функциональной. и возмущаться этим — всё равно что предъявлять претензии к математикам вообще, которые придумывают столь сложные теории для описания того, как яблоки падают на землю
Я вообще не разделяю идею впихивания математики в ЯП. ЯП давно и далего ушли от абстрактной математики.
Язык должен быть интуитивным, удобным и эффективным. И догматизм не лучший спутник в достижении этих целей. По сему оцениваю Хаскель как изумительную исследовательскую работу, но не как реальный прикладной язык.
Его идеи вроде классов типов и ленивости восхитительны. Но вот в таком вот виде, на мой взгляд, они не применимы на практике.
Я согласен с автором презитнации — язык должен быть не ленивым по умолчанию и лишь позволять ленивость там где это бывает удобно. Так же мне не рнавится идея полного отказа от императивного кода. Все же многие алгоритмы не реализуемы без императива. Та же быстрая сортировка на Хаскеле — это обман, так как фактическ демонстриует другой алгоритм (отнюдь не эффективный).
Меж тем для реального мира было бы достаточно помечать части кода как функциональные, императивные и ленивые. И это решило бы все пробелмы. Причем решило бы без перегрева мозга бедных программистов.
BZ> (ты в курсе, что матанализ появился именно для описания движения планет по круговым орбитам?)
Этот фак мне не интересен.
ЗЫ
В общем, я прекрасно понимаю суть наших разногласий. Я эдакий романтический програматик. Ине очень интересны красивые решения, но меня при этом еще заботят эффективность и применимость на практике. Ты же любишь чистые решения что бы они не стоили.
Я понимаю и уважаю эту точку зрения, но не разделяю ее.
Я считаю, что пришло время перевести мэйнстрим на языки которые будут мало отличаться от сегодняшних фоваритов (С++, C# и Java) по эффективности, но при этом дадут возможность существенно поднять уровень разработки.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
, как легко PM>такие конструкции определить. Для применения в ограниченном контексте PM>вполне подходит. Гипотетические проблемы с лифтингом, которые мы PM>обсуждали ниже, возникнут, если этот ограниченный контекст раздуть, и в PM>этом случае действительно желательно рассмотреть вариант с FFI. Иметь 2 PM>яызка в одном — не слишком хорошая идея, IMHO.
Блин, ну неужели трудно понять, что 90% здоровых на голву людей бросят сам язык когда дойдут до этого самого лифтинга. Это все равно что заливать в перегретый автомабиль воду из кипящего чайника!
И все это ради того чтобы не признать правды — мир императивен и "чистоту" надо просто отделять от "императивной грязи".
Эта концепция проста для понимания. А все эти лифтинги, реалврлды, монады и т.п. — это булш который никогда не даск языка вроде Хаскеля стать действительно популярными.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.