Здравствуйте, LaPerouse, Вы писали:
LP>Все-таки основным критерием функционального подхода является то, о чем я говорил выше – отношение к хранению состояния. Вот он, постамент, на котором зиждется вся теория и практика функционального программирования, тот самый “пятый элемент”, придающий особый колорит этому стилю. Стоит только разрешить изменение переменных в любом “функциональном языке” и внешние ссылки на эти переменные (которое не нужно даже специальным образом вводить), и этот язык неуловимо для глаз превратится в стандартный процедурный язык. Все остальное – синтаксические конструкции, помогающие объявлять вложенные конструкции функций, встроенные в сам язык возможности для обработки списков и т п — все это для дураков, чтобы дать им почувствовать всю “революционность” и крутизну “новейшего” подхода. Да! Я утверждаю, что за роскошной вывеской прячется тухлятина, которой уже как минимум 50 лет. И готов это доказать любому, пусть и придется пожертвовать частью личного времени на восполнение пробелов в чужом образовании.
Все-таки основным критерием ОО подхода является то, о чем я говорил выше – отношение к хранению состояния. Вот он, постамент, на котором зиждется вся теория и практика ООП, тот самый “пятый элемент”, придающий особый колорит этому стилю. Стоит только запретить классы в любом “ОО-языке” и объявления методов в них, и этот язык неуловимо для глаз превратится в стандартный процедурный язык. Все остальное – синтаксические конструкции, помогающие объявлять интерфейсы, встроенные в сам язык возможности итирации по коллекция и т п — все это для дураков, чтобы дать им почувствовать всю “революционность” и крутизну “новейшего” подхода. Да! Я утверждаю, что за роскошной вывеской прячется тухлятина, которой уже как минимум 50 лет. И готов это доказать любому, пусть и придется пожертвовать частью личного времени на восполнение пробелов в чужом образовании.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladGalkin, Вы писали:
VG>Mads Torgersen, C# Language PM, написал в своем блоге пост с говорящим названием: "Is C# becoming a functional language?". Автор демонcтрирует различные фичи функционального программирования на примере C# 3.0, отвечая на поставленый в название вопрос: "to some degree".
Опять-таки, ответ на этот вопрос зависит от того, с какой стороны стороны на него смотреть. Появились ли функциональные возможности — да!, появились ли функциональные возможности — нет! Возможность определения ламбды сама по себе не является свидетельством функциоанальности языка, хоя бы потому, что ламда является побочным следствием ФЯ, возникшем из-за стремления сократить и без того огромное количество функций в программе. Основной подход функционального программирования — принципиальное отрицание состояния как такового — не реализован даже опционально и не будет реализован никогда ни в этом языке, ни в никаком другом, претендующим на современность.
Честно говоря, мне непонятны все эти попытки связать нововведения в языке с "поддержкой функционального программирования". Функциональное программирование как парадигма устарела еще в 70-ых годах вместе с процедурным программированием, подвидом которого оно является. Все эти лямды следует рассматривать лишь как синтаксический сахар (как и вывод типа). призванный сократить запись и освободить программиста от рутинных объявлений.
Социализм — это власть трудящихся и централизованная плановая экономика.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Vermicious Knid, Вы писали:
VD>... VD>По-моему, зачательная демонстрация того, что простые и прямые решения лучше чем эмуляция. И не важно ради чего эта эмуляци делается, из соображений совместимости, или в пылу борьбы за чистоту.
Да-да-да.
Наш Вычислительный Центр продолжает исследования в области уточнения значений замечательных чисел. Очередной прорыв достигнут при помощи нового суперкомпьютера для точного вычисления единицы по формуле sin^2(x) + cos^2(x): теперь мы знаем, что среди первых тридцати миллионов знаков десятичного разложения нет отличных от нуля.
Это существенный прогресс по сравнению с предыдущим значением в миллион знаков. Зарубежные ученые встретили наши достижения завистливой критикой. "Вы страдаете &$%%!@ней", заявил профессор А. из НьюПорта, "которая не имеет никакого практического применения", а франзузский математик П. не замедлил ехидно поинтересоваться выбором числа x для вычислений и влиянием его точности на результаты.
На это наши ученые отвечают, не теряя достоинства:
Что касается выбора числа X, то в еще в прошлом году в Вестнике РАН уважаемый директор нашего ВЦ опубликовал статью, в которой полностью обосновал наш выбор. Полезность же наших работ может недооценить только человек, абсолютно не знакомый с наукой. Единица используется в огромном количестве теорем; в частности, новые результаты в очередной раз подтвердили основания теории функций комплексного переменного, обосновав принятое приближение для числа i = sqrt(-1) и окончательно похоронили ревизионистские поползновения империалистической науки.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Quintanar, Вы писали:
Q>Здравствуйте, LaPerouse, Вы писали:
LP>>Повторяю — функциональное программирование является разновидностью процедурного, нравится вам это или нет. Единственное отличие заключается в подходе к хранению состояния. Если задаться целью, можно и на С писать почти в функциональном стиле. Разница между императивным и функциональным программированием мне понятна, что и позволило мне прийти к такому умозаключению.
Q>Не является функциональное программирование разновидностью процедурного, нравится вам это или нет. Q>Объяснения по поводу того, что можно писать на С переадресуйте любителям С++. Я, например, знаю, что многие прекрасно пишут в объектно-ориентированном стиле на С и не жалуются. Тот факт, что на С можно, хоть и через Ж, писать в любом стиле, ничего не означает.
Прекрасно, давайте по пунктам. Единственным, я подчеркиваю, единственным ощутимым различием ФП от ИП является то, что в ФП запрещается "заморозка" состояния,в ИП — она разрешается. Вследствие чего появляется ЗАВИСИМОСТЬ ОТ ПОРЯДКА ВЫПОЛНЕНИЯ КОМАНД. Снадби любой процедурный язык способами более эффективной записи вызовов функций + встрой в язык некоторые операторы для обработки списков (что в нормальном языке реализуется библиотеками) — и получится чистейший функциональный язык. Остаеются только ленивые вычисления реализовать, но они не являются необходимым условием функциональности языка.
Впрочем, я никого не переубеждаю. Хочется вам думать, что ФП не являются вчерашним днем — думайте, кто же запрещает? Это не изменит аморальной сути функционального программирования.
Социализм — это власть трудящихся и централизованная плановая экономика.
BZ>>но ведь именно на это соображение я выше и ответил! представь себе скажем имя лог-файла, которое нужно передавать во все процедуры, поскольку запись в лог-файл может понадобиться где-то в самом низу иерархзии вызовов
VD>Представил. Теперь потрудись объяснить причем тут C#?
VD>В нем есть только два способа передать информацию — это глобальные переменные, и параметры методов. VD>Ничего нового в C# 3.0 в этом плане не появится.
самое смешное, что в хаскеле — тоже для записи императивных алгоритмов в pure & lazy языке типа хаскела и clean используется фиктивное значение типа real world, передаваемое в и возвразаемое любой императивной процедурой. оно передаётся по цепочке от порцедуры к процедуре, и таким образом компилятор думает, что все эти процедуры можно вызывать только последовательно, в явно заданном порядке (а кодлогенератор в то же самое время думает, что real world — это туфта, и при генерации кода его просто не замечает). вот смотри, если полностью рассахарить эту IO monad:
main realworld0 = let (rw1,ch1) = getChar realworld0
(rw2,ch2) = getChar rw1
(rw3,()) = putChar rw2 ch1
in (rw3,())
этот код читает два символа и затем выводит второй из них. но второй вызов getChar невозможно опустить, поскольку для вызова putChar требуется "состояние мира". которое может возвратить только он собственно, unique types в clean — это то же самое, с явным заданием каждого "мира", получаемого и возвращаемого каждым вызовом. но используя функции высшего порядка, можно от этого избавиться:
а do предоставляет для этого синтаксический сахар с закосом под императивные языки:
main = do ch1 <- getChar
ch2 <- getChar
putChar ch1
т.е. обратите внимание, что do-нотация чисто синтаксически транслируется в эту последовательность вызовов >>=
а теперь представьте, что вы делаете другую монаду, где вместо передачи туда-сюда фиктивного realworld передаётся что-то существенное, типа хендла этого лог-файла. явно этот вездессущий параметр упоминаться при вызовах не будет, но при этом прекрасно повсюду дойдёт. а для его использования нужно добавить пару операций, специфичных для этой монады (это монада State), которые позволяют читать и изменять её текущую невидимую переменную. представили?
а дальше идут monad transformers, которые представляют не просто одну монаду, а способ добавить к монаде новую функциональность. т.е. ввам не придётся например выбирать между Error monad (прекразает вычисление при возбуждении ошибки), State monad, Parsing monad (сохраняет текущее состояние бибилиотеки парсинга), а вы их можете объединить вместе, наслоив одну на другую и использовать всю необходимую вам функциональность в общем коде. более того, вы можете добавить в этот бутерброд новые монады по мере развития программы, а эта запись do с вызываемыми в ней процедурами останется неизменной
я кстати слышал о реализации энтузиастами монад для питона и схемы. так что возможно. но конечно использовать их там, как и в C* — не фунт изюму
ps: более подробно реализация IO monad описана в http://haskell.org/haskellwiki/IO_inside . один преподаватель колледжа даже говорил, что использует этот текст в своих курсах
Здравствуйте, Mirrorer, Вы писали:
M>Суть какая. Пишется простейший интерпретатор. Типа того что ты приводил в каком-то посте про Nemerle. Потом к нему добавляется обработка ошибок. Потом к нему добавляется вывод позиции ошибки. Причем развитие делается с минимумом телодвижений. По возможности. И с объяснениями как бы это могло выглядеть без монад. M>Мой поинт заключается в том, что монадную технику приводимую в статье можно с успехом использовать не только в Хаскеле. То есть код можно практически один в один преписать на Немерле и оно будет работать. Если есть способ написать аналог интерпертатора с меньшими телодвиженями — welcome.
На самом деле я себе не могу представить как можно написать аналог этого интерпретатора с большими телодвижениями. Использовать такую технику в языках отличных от Хаскелла смысла не вижу. А в этой программе вижу только костыли, с помощью которых на хаскелле пытаются обойтись без состояния и исключений. Чуть ли не половина кода это какие-то левые монадные манипуляции, не имеющие никакого отношения к сути происходящего. Думаю и на Хаскелле такое лучше писать без монад. Будет конечно больше кода, но зато его смогут понимать не только представители внеземного разума, но и простые люди вроде меня.
В "императивном" мире куча способов написать это с меньшими телодвижениями и без монад. Самое простое — исключения. Монады в данном примере как раз играют роль непопулярных, и вполне заслуженно, в ООП кодов возврата. Но можно обойтись и без исключений, и без телодвижений.
Реализовывать этот пример один в один мне было не интересно, поэтому я добавил функциональности. Интерпретатор находит не одну ошибку, а список. Еще в Nemerle нет автоматического претти-принтера для алгебраических типов, поэтому я реализовал преобразование в текст более-менее близкий к предположительному исходному языку(это добавляет 12 строчек, но программа и без них будет компилироваться и "работать"). Вот вариант без позиционирования(sorry за привычный мне синтаксис без фигурных скобок и излишнюю "сжатость" кода):
variant Value
| Error { lst : list[string * Term] }
| Num { value : int }
| Fun { f : Value->Value }
public override ToString() : string
match(this)
| Num(value) => value.ToString()
| Fun(_) => "<function>"
| Error(lst) => $"<$(lst.Length) error(s)>"
variant Term
| Var { name : string }
| Constant { value : int }
| Add { l : Term; r : Term }
| Lambda { name : string; expr : Term }
| Apply { l : Term; r : Term }
public Eval(environment : list[string * Value]) : Value
def eval(x) : Value { x.Eval(environment) }
def errors(lst)
Value.Error($[e | (errs is Value.Error) in lst, e in errs.lst])
match(this)
| Var(name) => match(environment.Find((n, _) => n == name))
| Some((_, value)) => value
| None => Value.Error([($"unbound variable : $name", this)])
| Add(l, r) => match((eval(l), eval(r)))
| (Num(x), Num(y)) => Value.Num(x + y)
| (x, y) => errors([x, y, Value.Error([($"should be numbers : $l, $r", this)])])
| Apply(l, r) => match(eval(l))
| Fun(f) => f(eval(r))
| v => errors([v, eval(r), Value.Error([($"should be a function : $l", this)])])
| Lambda(name, expr) => Value.Fun(param => expr.Eval((name, param) :: environment))
| Constant(value) => Value.Num(value)
public override ToString() : string
match(this)
| Var(name) => $"var($name)"
| Constant(value) => $"$value"
| Add(l,r) => $"$l + $r"
| Lambda(name, expr) => $"(\\$name -> $expr)"
| Apply(l, r) => $"$l $$ $r"
Теперь по поводу телодвижений. Предположим, что был пример без обнаружения ошибок. Чтобы его получить нужно просто убрать несколько строчек кода — тогда программа в случае ошибок в ast просто будет вываливаться с MatchFailureException(или что-то в этом роде). Правда будет несколько предупреждений при компиляции.
А чтобы добавить вывод позиции ошибки вышеприведенный код и вовсе менять не обязательно. Вот пример использования в котором предусмотренно позиционирование ошибки:
// весь этот код в отдельном файлеusing System.Console
using Nemerle.Collections
// это чтобы упростить создание ast вручнуюusing Term
def test(term : Term, locations)
def value = term.Eval([])
WriteLine($"'$term' evaluates to $value.")
// если были ошибки, вывести их расшифровку
match(term.Eval([]))
| Error(lst) =>
foreach((msg, term) in lst)
WriteLine($"Error : $(locations.GetValueOrDefault(term, -1)) : $msg")
| _ => ()
def term1 = Apply(Constant(0), Var("x"))
// имхо незачем замусоривать ast локациями, пусть они будут отдельно
def locations = Hashtable()
// добавим локации веток ast в исходном тексте выражения "0 $ x"
// конечно это должно делаться в парсере
match(term1)
| Apply(_, Var as l4) as l2 =>
locations.Add(l2 : Term, 2)
locations.Add(l4, 4)
| _ => ()
test(term1, locations)
// (\y -> (\x -> x + x) $ y) $ 1
def term2 = Apply(Lambda("y", Apply(Lambda("x", Add(Var("x"), Var("x"))), Var("y"))), Constant(1))
test(term2, locations)
Результат выполнения этой программы:
'0 $ var(x)' evaluates to <2 error(s)>.
Error : 4 : unbound variable : x
Error : 2 : should be a function : 0
'(\y -> (\x -> var(x) + var(x)) $ var(y)) $ 1' evaluates to 2.
Теперь пример с использованием исключений и без лишней функциональности, полученный из вышепревиденного примера:
using System.Console
using Nemerle.Collections
using Nemerle.Utility
variant Value
| Num { value : int }
| Fun { f : Value->Value }
variant Term
| Var { name : string }
| Constant { value : int }
| Add { l : Term; r : Term }
| Lambda { name : string; expr : Term }
| Apply { l : Term; r : Term }
[Record] public class EvalException : System.Exception
[Accessor] description : string
[Accessor] term : Term
public Eval(environment : list[string * Value]) : Value
def eval(x) : Value { x.Eval(environment) }
match(this)
| Var(name) => match(environment.Find((n, _) => n == name))
| Some((_, value)) => value
| None => throw EvalException($"unbound variable : $name", this)
| Add(l, r) => match((eval(l),eval(r)))
| (Num(x), Num(y)) => Value.Num(x + y)
| _ => throw EvalException($"should be numbers : $l, $r", this)
| Apply(l, r) => match((eval(l),eval(r)))
| (Fun(f), p) => f(p)
| _ => throw EvalException($"should be a function : $l", this)
| Lambda(name, expr) => Value.Fun(param => expr.Eval((name, param) :: environment))
| Constant(value) => Value.Num(value)
def term = Term.Apply(Term.Constant(0), Term.Var("x"))
def locations = Hashtable()
match(term)
| Apply(_, Var as l4) as l2 =>
locations.Add(l2 : Term, 2)
locations.Add(l4, 4)
| _ => ()
try
WriteLine(term.Eval([]))
catch
| err is Term.EvalException =>
def location = locations.GetValueOrDefault(err.Term, -1)
WriteLine($"Error : $location : $(err.Description)")
(C) lomeo > И второе имхо выглядит весьма достойно и понятно. А это ничто иное > монада List.
Выглядит ни грамма не понятно, и это все та же монада List .
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)
LP>Все-таки основным критерием функционального подхода является то, о чем я говорил выше – отношение к хранению состояния. Вот он, постамент, на котором зиждется вся теория и практика функционального программирования, тот самый “пятый элемент”, придающий особый колорит этому стилю. Стоит только разрешить изменение переменных в любом “функциональном языке”
Зачем?
LP>и внешние ссылки на эти переменные (которое не нужно даже специальным образом вводить),
Зачем? И потерять такую важную вещь, как удобство в распараллеливании программ?
LP>и этот язык неуловимо для глаз превратится в стандартный процедурный язык.
Зачем?
LP>Все остальное – синтаксические конструкции, помогающие объявлять вложенные конструкции функций, встроенные в сам язык возможности для обработки списков и т п — все это для дураков, чтобы дать им почувствовать всю “революционность” и крутизну “новейшего” подхода.
Предположим, не революционность, а эволюционность.
За возможность написать map(Fun, List) я бы продал Страуструпа с Виртом в рабство. Обоих
LP>Да! Я утверждаю, что за роскошной вывеской прячется тухлятина, которой уже как минимум 50 лет. И готов это доказать любому, пусть и придется пожертвовать частью личного времени на восполнение пробелов в чужом образовании.
Ну, не 50, а больше. Если я не ошибаюсь, все началось в далеких 1930-х годах, когда Черч и Клин начали разрабатывать лямбда-исчисление. Правда, поняли это только в 1960-х. Хорошая цитата оттуда:
Most programming languages are rooted in the lambda calculus, which provides the basic mechanisms for procedural abstraction and procedure (subprogram) application.
The most prominent counterparts to lambda calculus in programming are functional programming languages, which essentially implement the calculus augmented with some constants and datatypes.
То есть функциональные языки являются наиболее полной реализацией лямбда-исчисления на практике. И прочие языки меееедленно подбираются к этому. Зачем им подбираться к тухлятине? Быть может, не такая уж это и тухлятина?
Здравствуйте, VladD2, Вы писали:
VD>Язык должен быть интуитивным, удобным и эффективным. И догматизм не лучший спутник в достижении этих целей. По сему оцениваю Хаскель как изумительную исследовательскую работу, но не как реальный прикладной язык.
Влад, ты таки уловил основные задачи языка. Вот его авторы рассказывают о целях, которые ставились перед языком, при его создании:
The first order of business was to establish the following goals for the language:
1. It should be suitable for teaching, research, and applications, including building large systems.
2. It should be completely described via the publication of a formal syntax and semantics.
3. It should be freely available. Anyone should be permitted to implement the language and distribute it to whomever they please.
4. It should be usable as a basis for further language research.
5. It should be based on ideas that enjoy a wide consensus.
6. It should reduce unnecessary diversity in functional programming languages. More specifically, we initially agreed to base it on an existing language, namely OL.
Т.е. никто и не пытался занять нишу C++/Java/C#.
VD>Его идеи вроде классов типов и ленивости восхитительны. Но вот в таком вот виде, на мой взгляд, они не применимы на практике.
Так он и создавался для того, чтобы быть на переднем краю в исследованиях функциональных языков.
VD>В общем, я прекрасно понимаю суть наших разногласий. Я эдакий романтический програматик. Ине очень интересны красивые решения, но меня при этом еще заботят эффективность и применимость на практике. Ты же любишь чистые решения что бы они не стоили.
VD>Я понимаю и уважаю эту точку зрения, но не разделяю ее.
VD>Я считаю, что пришло время перевести мэйнстрим на языки которые будут мало отличаться от сегодняшних фоваритов (С++, C# и Java) по эффективности, но при этом дадут возможность существенно поднять уровень разработки.
Haskell и есть та экспериментальная площадка, на которой обкатываются идеи, которые попадают в мейнстрим.
На channel9 есть куча интервью с дядками, которые двигают различные исследовательские проекты (LINQ, PLINQ, STM,...),
многое из которых потом пойдёт дальше для простых смертных.
Так вот они постоянно упоминают Haskell как один из основных инструментов.
На LtU давеча пробегала концепция "fuctional OO programming" (которая, мол, и есть самая правильная): http://lambda-the-ultimate.org/node/2007 (и далее по ссылками).
Программирование, в котором функциональный стиль не используется, остроумно названо дисфункциональным
LaPerouse wrote: > Прекрасно, давайте по пунктам. Единственным, я подчеркиваю, единственным > ощутимым различием ФП от ИП является то, что в ФП запрещается > "заморозка" состояния,в ИП — она разрешается.
Нет. Единственным, я подчеркиваю, единственным ощутим различием является
ФП от ИП является использование ФВП — Функций Высших Порядков. ВСЁ
Порядок вычислений — не важен, есть функциональные языки с
eager-вычислениями, в которых порядок вычислений вполне определен.
Лямбды — это действительно просто сахар, хотя такой же необходимый для
ФП, как и циклы for/while для ИП, которые являются сахаром над if/goto.
ФП невозможен без какой-либо формы ФВП. А вот процедурные языки —
вполне возможны. В некоторых процедурных языках даже нельзя взять
указатель на функцию, а значит ФП не может быть подмножеством
процедурного стиля.
Здравствуйте, konsoletyper, Вы писали:
K>Пусть у нас есть функция f(x, y, t), а функциональный дисплей сделан на основе ЭЛТ. Тогда дисплей во время хода луча просто вызывает эту функцию с различными (x, y), но с постоянной t. На следующем кадре (пусть это происходит через 0.01 сек) монитор прибавляет к t 0.01 и повторяет всю операцию уже с другим t.
Здравствуйте, Klapaucius, Вы писали:
K>Здравствуйте, Mirrorer, Вы писали:
M>>Но это в том случае если принять, что указатель на функцию == функции.
K>Так в том и дело, что указатель на функцию != функции. K>Собственно, в той же Википедии и об этом написано здесь
А. Вроде разобрался. Просто у меня была путаница между ФВП и First-Class Function.
Итого. Получается что ФВП действительно то, что написано в википедии
In mathematics and computer science, higher-order functions or functionals are functions which do at least one of the following:
* take one or more functions as an input
* output a function
А First-Class Function это
In computer science, a programming language is said to support first-class functions if it treats functions as first-class objects. Specifically, this means that functions can be created during the execution of a program, stored in data structures, passed as arguments to other functions, and returned as the values of other functions.
Причем
The modern, natively compiled programming languages support functions defined statically at compile time. Most of them, e.g. C and Pascal, additionally support function pointers, which can be stored in data structures and passed as arguments to other functions. Nevertheless, they are not considered to support first class functions, since, in general, functions cannot be created dynamically during the execution of a program. The closest analog would be a dynamically compiled function created by a just-in-time compiler, which is compiled as an array of machine language instructions in memory and then cast to a function pointer. However, this technique is specific to the underlying hardware architecture and is, therefore, neither general nor portable.
Здравствуйте, Cyberax, Вы писали:
C>LaPerouse wrote: >> Повторяю — функциональное программирование является разновидностью >> процедурного, нравится вам это или нет. C>Да даже близко не является. Процедурное программирование — это C>подмножество императивного стиля.
C>Функциональное программирование — это совершенно другой стиль. C>Ортональный ООП и противоположный императивному.
Видите ли, те языки, о которых вы говорите (C++, Pascal) в представлении многих являются классическими процедурными языками, что нет ничего недопустимого в усилении этого термина, которое более предпочтительно по сравнению с введением нового термина – “функциональный язык”. Исходя из того, что сказано мной выше, едва ли справедливо выделять из процедурных группу функциональных языков, тут, скорее, нужно говорить о “функциональном подходе” и о языках, наиболее эффективно поддерживающих этот подход.
Все-таки основным критерием функционального подхода является то, о чем я говорил выше – отношение к хранению состояния. Вот он, постамент, на котором зиждется вся теория и практика функционального программирования, тот самый “пятый элемент”, придающий особый колорит этому стилю. Стоит только разрешить изменение переменных в любом “функциональном языке” и внешние ссылки на эти переменные (которое не нужно даже специальным образом вводить), и этот язык неуловимо для глаз превратится в стандартный процедурный язык. Все остальное – синтаксические конструкции, помогающие объявлять вложенные конструкции функций, встроенные в сам язык возможности для обработки списков и т п — все это для дураков, чтобы дать им почувствовать всю “революционность” и крутизну “новейшего” подхода. Да! Я утверждаю, что за роскошной вывеской прячется тухлятина, которой уже как минимум 50 лет. И готов это доказать любому, пусть и придется пожертвовать частью личного времени на восполнение пробелов в чужом образовании.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Социализм — это власть трудящихся и централизованная плановая экономика.
BulatZiganshin,
VD>>Казалось бы. Пометь блок кода и скажи, что он должен выполняться последовательно и не лениво. И все! Пиши себе в других местах пользуясь всеми приемуществами линивости, а когда надо просто переключайся в императив. Но нет, мы создаем себе сказку и усилиенно пытаемся поверить в нее. В итоге получаем тоже самое, но сложно, запутано и медленно.
BZ>во-первых, там просто нет блоков кода. описания в чисто математическом ключе:
BZ>
BZ>f x = let y = x*2
BZ> z = y+3
BZ> in y*z
BZ>
BZ>т.е. вставить в такой набор мат. равенств вызовы процедур довольно проблематично. во-вторых, это потребовало бы больших переделок в языке и компиляторах, поскольку нарушило бы чистоту языка и независимость результата от порядка вычислений. т.е. пришлось бы вводить спец. правила взаимодействия императивного и чистого кода.
Теперь и мне придётся выступить в роли оппонента
Я думаю, все отлично понимают отличия функций в языке программирования от функций в математике. В математике f: X->Y не предполагает, что f будет вычисляться, и вычисление займёт какое-то время. Вообще, понятия вычисления и времени нет, пока их явно не вводить.
Например, в математике (например, теория меры) запросто можно сказать: пусть U = f^{-1}(V) — прообраз множества V. Всё, дальше мы можем использовать множество U. И нас вообще не заботят следующие малозначительные детали как:
1. f (u) вычислить тяжело, практически невозможно, или даже теоретически невозможно;
2. f^{-1} (v) вычислить тяжело, практически невозможно, или даже теоретически невозможно;
3. Предикат u \in U вычислить тяжело, практически невозможно, или даже теоретически невозможно;
4. Предикат v \in V вычислить тяжело, практически невозможно, или даже теоретически невозможно;
5. Я уже не говорю, что сами множества U и V могут быть какими-нибудь неизмеримыми, или бесконечными, или бесконечномерными, или ещё какими-нибудь эдакими...
То есть я хочу сказать, что автоматически переносить понятие функции из математики в программирование может быть просто непрактично.
Вот теперь я вернусь обратно. Предположим, я ввожу соглашение (примерно то, что Влад предлагает): функции, которые в реализации используют нечистые конструкции, по соглашению будут начинаться с подчёркивания. Но чтобы избежать транзитивного замыкания грязи, мы вне таких функций будем пользоваться нашими старыми знакомыми — монадами:
_solve :: Matrix Int -> Vector Int -> Vector Int
_solve m b = -- далее идёт метод решения СЛАУ с матрицей m и правым столбцом b скажем методом LU
-- разложения, здесь можно использовать традиционный доступ к мутабельным массивам,
-- циклы и т.п.
-- компилятор рассматривает эту функцию как неделимую сущность
main :: IO () -> ()
main = do
(m, b) <- loadSLAE("slae.txt")
putStrLn (show $ _solve m b)
Таким образом мы можем устранить все критичные участки, что с _практической_ точки зрения благо. Разумеется, этот метод должен применяться только в качестве последнего средства (после ! и seq).
И что самое интересное, подобная возможность уже в Хаскеле есть — это FFI. Вот мне любопытно, что такого плохого станется, если поднять императив на уровень языка и использовать его в ограниченном контексте? Это несколько некомфортно с идеологической точки зрения, но практически полезно.
ps: (боже мой!!! неужели это сказал я!!! ААААА!!!)
EC>Language Integrated Query (LINQ) is a framework that is rooted
EC>in the theoretical ideas of monads and monad comprehensions to
EC>allow seamless querying over objects, XML, and relational data.
Все таки стоит различать монаду как математический термин, и монаду как реализацию в функц. языка(там указано именно теоретические идеи). Это не есть совсем одно и то же, хотя и близкие понятия. Если брать функц. языки, то в данном случае как аналог исчисления монад больше подходит list comprehension. Да и во многом, если говорить именно о Linq, надо вообще говорить о monoid calculus.
Вобщем здесь не все так просто.
VD>Люди принимают догмат "чистоты", но сразу же придумывают другой догамт позволяющий эту чистоту обойти. Казалось бы так все просто. В ФЯ любая функция при одном наборе аргументов обязана вернуть один определенный результат. Это помогает во многих случаях. Там распраллеливание, простота отладки, и еще много чего, но вот увы это не вяжется с реальным миром. В любом ООЯ мы просто создали бы объект в который положили бы ссылку на перменную или, как это предлагаешь ты, на хитрый объект сервис-локатор, но увы у нас догмы. Мы не может это сделать. Тогда мы придумываем хитрую чтоуку называем ее поумнее и вуаля обходим наши же ограничения.
на момент создания хаскела такой язык уже был — ML более того, как сказано в той самой history of haskell, делая lazy язык, поневоле приходишь к pure языку — эти вещи не строго взаимосвязаны, но иначе получается неудобно. в результате в хаскеле появилось два варианта для организации i/o, затем наконец пришли к третьему — монадам. кстати, статья "Imperative Functional Programming" http://www.haskell.org/ghc/docs/papers/imperative.ps.gz была признана оказавшей наибольшее влияние на всё FP в 90-х годах!
далее. сделав в языке две ипостаси — чистые функции и процедуры, ты должен будешь продумать язык отдельно для каждой из них, продумать их правила взаимодействия и т.п. затем эта удвоенная сложность выльется в компиляторы, в понятия программирования и т.д. почему, думаешь, в С вместо отдельного процедурного типа использовали функции типа void? для концептуальной простоты.
здесь же потери были бы ещё больше. и никакого выигрыша. фактически, сам pure язык позволяет сформулировать концепцию процедуры в нём, используя этот трюк с realworld. и тогда вместо того, чтобы формулировать правила для процедур отдельно, они просто выводятся из общих правил для любых pure функций, становятся их частным случаем. общее кол-во концепций в языке уменьшается, а это не может не радовать
далее. на самом деле отнюдь не монады имитируют императивное программирование. его имитируют фиктивные значения realworld. в некоторых других языках (clean, mercury) такие значения тоже используются. разница только в том, что в тех языках синтаксический сахар был направлен непоредственно на убирание этих мозолящих глаза параметров, а в хаскеле пошли дальше и спрятали их с помощью higher-order функции >>= :
putChar 'a' >>= putChar 'b'
эквивалентно
let (rw1,_) = putChar 'a' rw0
(rw2,x) = putChar 'b' rw1
in (rw2,x)
как видишь, одна эта операция без всяких монад, лёгкой джазовой походкой, избавляется от необходимости явного упоминания фиктивного параметра. и синтаксический сахар в Хаскел генерит не непосредственно фиктивные параметры, как в других языках, а вот эти вызовы >>=
что же касается концепции монад, это это уже было обобщение этого паттерна, использование его в других областях. на данный момент можно сказать, что монады — это стратегия вычислений, определяемая отдельно от самих этих вычислений
Здравствуйте, VladD2, Вы писали:
VD>Люди принимают догмат "чистоты", но сразу же придумывают другой догамт позволяющий эту чистоту обойти. Казалось бы так все просто. В ФЯ любая функция при одном наборе аргументов обязана вернуть один определенный результат. Это помогает во многих случаях. Там распраллеливание, простота отладки, и еще много чего, но вот увы это не вяжется с реальным миром. В любом ООЯ мы просто создали бы объект в который положили бы ссылку на перменную или, как это предлагаешь ты, на хитрый объект сервис-локатор, но увы у нас догмы. Мы не может это сделать. Тогда мы придумываем хитрую чтоуку называем ее поумнее и вуаля обходим наши же ограничения.
Влад. Для начала нужно понять что такое догмат "чистоты" в особенности со стороны компилятора. Это не Lazy. Lazy — всего лишь одна из оптимизаций. Догмат чистоты — это совершенная простота уравнений доступных компилятору. Программу состоящую из терминов atom, sequence и function — можно представить и в виде системы комбинаторных уравнений и в виде графа. И соответвенно преобразовать данный граф автоматически к наиболее эффективному виду. Фактически, это теоретическая возможность построения оптимизатора по сравнению с которым оптимизаторы императивных языков — дети неразумные. И собственно к этому все и движется. Только там слишком много NP задач. Во многом, это похоже на ситуацию с оптимизацией SQL.
В теоретическом будущем, ситуация с pure functional и императивным языком, будет такая же как с C и ассемблером. На ассемблере можно делать очень эффективные программы — но для этого необходимы знание не меньшие чем у разработчиков компилятора C.
Если отказаться от догмата — то нужно отказаться от этого будущего.
А монады — непротиворечат pure. Они лишь вводят новый закон нетранзитивности.
Здравствуйте, Sinclair, Вы писали:
L>>Почему опять трудится должен я? Потрудись перечитать мой ответ. Что тебе в нём непонятно?
S>Вступлюсь: мне тоже непонятно.
поскипал, извини, там кроме эмоций ничего нет.
S>Тебе что, и вправду непонятно, что именно в приведенном рекламном лозунге вызывает недоумение? Обычно, когда люди говорят, что-то вроде "кошка похожа на собаку", им не очень трудно пояснить, что у них есть какие-то общие свойства. К примеру, что и кошек и у собак есть хвост.
Я показывал общие свойства.
S>Вот мне, к примеру, жутко интересно, что общего у Linq и монад. Мое несовершенное понимаение монад сводится к чему-то вроде "способ управлять композицией функций". В Linq ничего похожего на управление способом композиции функций нет.
Наверное, на монаду можно смотреть по разному. Как и на любой достаточно абстрактный предмет.
Здесь твой взгляд ничем нам не поможет, и поэтому я вынужден провести маленький ликбез. Извини, если говорю прописные для тебя истины, но он нам нужен, чтобы у нас была общая база для обсуждений.
Итак у монад есть основные свойства. В частности, это операция bind, связывающая монаду с вычислением над её значением.
bind имеет тип m a -> (a -> m b) -> m b. Это означает, что мы можем взять одну монаду и (здесь важно!) функцию, которая принимает значение типа значения из монады (a) и возвращает новую монаду. Таким образом мы, работая с функциями над значениями, связываем монады над этими значениями. Это очень полезное свойство, позволяющее прятать стратегию этой связки.
Для нас всё выглядит работой над значениями do1 `bind` do2 `bind` do3 ...
Здесь doX :: a -> m b. Обычно конкретная монада прячет даже вот этот возврат (m b), чтобы работа была только над значениями. Например:
do x <- get
put (x + 2)
return x
Или, принимая функцию в качестве параметра — update (+2).
Здесь вообще не видно никакой монады — идёт работа над значениями. Функции get, put, return прячут от нас возврат монады.
Допустим, мы разрабатываем конкретную монаду в C#. Ну, предположим, у нас есть время поизвращаться. Дальше код условный, я на С# не пишу. В качестве монады мы берём тип IEnumerable<T>. Значит, функции, подверженные связке будут иметь тип что то вроде IEnumerable<B> foo<A,B>(A x). Ну A и B могут быть одними и теми же. Назовем этот тип Foo. Его можно сделать делегатом. Bind будет иметь тип IEnumerable<B> Bind<A,B>(IEnumerable<A> m, Foo<A,B> f). Семантика простая — для каждого значения A из m зовем f, потом всё склеиваем в новый IEnumerable. Ну и пусть она будет extension методом.
Теперь мы можем получить что то вроде m.Bind(Do1).Bind(Do2)...
Обратим внимание на два момента — первое — в C# Bind надо писать явно и второе — функций DoX у нас по задаче ограниченное количество — Where, Select и т.д., поэтому его можно вшить в функции Bind_DoX, а саму эту функцию сделать по аналогии с функцией update — простая задача обощения.
Вот и всё. От монад мы легко пришли к LINQ — я показал, что у них есть общего?
S>Если ты так хорошо понимаешь суть сходства Linq и монад, тебе не составит труда кратко обозначить, какие из перечисленных мной возможностей связывают между собой эти понятия. Не отвечая вопросом на вопрос и не ссылаясь на ссылки на цитаты. А?
Я это сделал ещё в том своём посте. В этом всего лишь разжевал. Если твоя цель — не флейм, то велкам обсудить. Если флейм — то велкам бросаться помидорами
Здравствуйте, VladD2, Вы писали:
VD>Лисп прородитель всех ФЯ. В нем концепции ФЯ были сормированы и опробированы. Все ФЯ клоны лиспа в некотором смысле.
Можно сказать больше. Прародителем является лямбда-исчисление. Лямбда исчисление — функциональные машинные коды. Лисп — функциональный ассеблер. ML — функциональный C. OCaml — функциональная Java.
Mads Torgersen, C# Language PM, написал в своем блоге пост с говорящим названием: "Is C# becoming a functional language?". Автор демонcтрирует различные фичи функционального программирования на примере C# 3.0, отвечая на поставленый в название вопрос: "to some degree".
As many of you will be aware, C#3.0 is adding a significant number of new language features. While the overall driving force behind putting these features in is the support of LINQ (Language INtegrated Query), the way we do it is strongly inspired by functional programming techniques. Moreover, we strive to make the new features as general-purpose as possible (with the exception of query expressions – they are undeniably tied to the querying domain!), so they do come out as features that will enable more of a functional style of programming.
This begs the question: Are we making C# a functional language?
This of course is a vague question. First of all, what exactly is a functional programming language? What does it take to qualify? Rather than trying to define the canonical list of language features that you have to have to be functional, I think it makes more sense to define it as “a language that supports a functional style of programming.”
Здравствуйте, Quintanar, Вы писали:
Q>Здравствуйте, LaPerouse, Вы писали:
LP>>Честно говоря, мне непонятны все эти попытки связать нововведения в языке с "поддержкой функционального программирования". Функциональное программирование как парадигма устарела еще в 70-ых годах вместе с процедурным программированием, подвидом которого оно является. Все эти лямды следует рассматривать лишь как синтаксический сахар (как и вывод типа). призванный сократить запись и освободить программиста от рутинных объявлений.
Q>Ну да, конечно. Поразительный факт состоит только в том, что функциональное программирование начало развиваться только в конце 70-х. Именно тогда появились ML и первый функциональный диалект Lisp — Scheme. Если вы не понимаете фундаментальной разницы между императивным и функциональным подходом к написанию программ, лучше не позорьтесь, промолчите.
Повторяю — функциональное программирование является разновидностью процедурного, нравится вам это или нет. Единственное отличие заключается в подходе к хранению состояния. Если задаться целью, можно и на С писать почти в функциональном стиле. Разница между императивным и функциональным программированием мне понятна, что и позволило мне прийти к такому умозаключению.
Социализм — это власть трудящихся и централизованная плановая экономика.
Здравствуйте, LaPerouse, Вы писали:
LP>Опять-т аки мой ответ адресуется обеим участникам, ответившим на мой вопрос, хотя и расположен вынужденно в неподобающем месте (что за скверный движок форума).
Интересно, почему люди увидя что-то новое и не успев привыкнуть к нему, сразу же начинают исать недостатки в этом новом и никогда не задумываются над тем, что недостаток в них (например, привычка к плохому)?
Вот, ты, например, увидил форум и начал возмущаться, что мол движок у него скверный. Меж тем достаточно понять, что в этом движке просто не надо отвечать сразу 10 человекам. Это и не конструктиво, так как они ведь не хором говорят. Отвечай себе конкретно на конкретные замечания и будет все ОК. Но привычка явно сильнее.
Та же ерунда и с взглядом на ФП. Увидил что-то, посчяитал его новым и пошел сразу искать недостатки. А надо ли с этого начинать? Может ради объективности сначала попробовать поглядеть и на достоинства?
Почему скажем наличие классов, библиотек коллекций, и других прибамбасов привычных для ООП — это нормально и даже наверно хорошо, а наличие:
синтаксических конструкций, помогающих объявлять вложенные конструкции функций, встроенные в сам язык возможности для обработки списков и т п — все это для дураков, чтобы дать им почувствовать всю “революционность” и крутизну “новейшего” подхода.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladGalkin, Вы писали:
VG>А Вы не кащенит ли случаем?
Что то мне не очень нравятся подобные шутки, прямо попахивающие оскорблением. Просьба разделять несогласие с утверждениями автора и личность самого автора.
Здравствуйте, VladD2, Вы писали:
VD>Ага. Вот фанаты чистой функциональности и изобретают шизу вроде фукнций на входе которых один мир, а на выходе другой. А по жизни это всего лишь выверты чтобы не видить основной проблемы — императивности мира.
Ты уверен, что то, что ты их не понимаешь делает их шизой?
Я вот не понимаю, но так не думаю.
VD>В общем, я расцениваю попытки обосновать разные монады и другие трюки как попытку подставить в уравнение недостающую констануту. Уравнение конечно может и сойтись, но вот чуство обмана все равно остается.
Интересно, с выходом LINQ твоё мнение изменится на прямо противоположное? Хинт.
Заметь, этим занимается знатный хаскелист Erik Meijer, такой попсовой штукой как VB и LINQ.
now playing: Boards of Canada — Telephasic Workshop
EC>Как видишь довольно общая идея, применение которой можно найти не только в Haskell. EC>Механизмы LINQ (трансформация одной последовательности в другую) ложаться в её рамки, EC>а то, о чём ты говоришь не более чем частные случаи.
Народ, не тратьте силы понапрасну.
Здравствуйте, VladD2, Вы писали:
VD>Это самовнушение. Физически проблем вызова "чистым кодом" "не чистого" нет. Ее придумали пуристы. И доказано это на практике.
Физически проблемы взятия адреса переменной в памяти и доступа к ней по этому адресу тоже нет. И кто тут ругает C++ за такую возможность? А после запрета доступа по адресу наворачиваются всякие value- и ref-типы, boxing и unboxing. Казалось бы, объект — это просто кусок памяти, неважно какой (стек, куча).
Позволь всё-таки существовать функциональным языкам, а не только смешанным.
Здравствуйте, EvilChild, Вы писали:
EC>Здравствуйте, VladD2, Вы писали:
VD>>Язык должен быть интуитивным, удобным и эффективным. И догматизм не лучший спутник в достижении этих целей. По сему оцениваю Хаскель как изумительную исследовательскую работу, но не как реальный прикладной язык.
EC>Влад, ты таки уловил основные задачи языка. EC>Вот его авторы рассказывают о целях, которые ставились перед языком, при его создании:
EC>
EC>The first order of business was to establish the following goals for the language:
EC>1. It should be suitable for teaching, research, and applications, including building large systems.
EC>2. It should be completely described via the publication of a formal syntax and semantics.
EC>3. It should be freely available. Anyone should be permitted to implement the language and distribute it to whomever they please.
EC>4. It should be usable as a basis for further language research.
EC>5. It should be based on ideas that enjoy a wide consensus.
EC>6. It should reduce unnecessary diversity in functional programming languages. More specifically, we initially agreed to base it on an existing language, namely OL.
Думаю ты на настолько глуп чтобы думать, что я приписывал эти черты Хаскелю. Авторам этого языка к сожалению не удалось создать язык отвечающий этим требованиям. Хаскель интуитивен только узкому кругу людей с математиким бэкэндом. Меж тем программирование уже давно вышло за рамки математики.
EC>Т.е. никто и не пытался занять нишу C++/Java/C#.
Претендуют, еще как. Только большинству эта ниша просто не позубам.
EC>Так он и создавался для того, чтобы быть на переднем краю в исследованиях функциональных языков.
Это ему удалось.
VD>>Я считаю, что пришло время перевести мэйнстрим на языки которые будут мало отличаться от сегодняшних фоваритов (С++, C# и Java) по эффективности, но при этом дадут возможность существенно поднять уровень разработки.
EC>Haskell и есть та экспериментальная площадка, на которой обкатываются идеи, которые попадают в мейнстрим.
Ты внимательно читал то что я написал прежде чем отвечать? Или у тебя прицип в жизни такой отчечать все что угодно лиш бы оно не имело никакого отношения к словм оппонентов?
EC>На channel9 есть куча интервью с дядками, которые двигают различные исследовательские проекты (LINQ, PLINQ, STM,...), EC>многое из которых потом пойдёт дальше для простых смертных. EC>Так вот они постоянно упоминают Haskell как один из основных инструментов.
И что? Это из серии услышал звон незнаю где он.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
AVK>>Про ужасную сложность передачи логгера внутрь кода без монад не я рассказывать начал, так что притензии не ко мне. У меня с логгером никогда никаких проблем не было.
VD>Я тебе еще раз повторяю, что у они себе сами объясняют как боросться с тараканами которых они сами же запустили в свою голову.
На словах — граница между интерпретацией и фактом очень тонка. Например, эти же самые слова абсолютно применимы к тебе, когда ты пытаешься объяснить появление монад. Ты решил, что мир императивен, и сделал из этого вывод, что императивные конструкции нужны. А когда увидел, что необходимости в них нет, и что все задачи, которые решает императив точно так же решает и другая модель, то ты начинаешь бороться с собственными тараканами, оправдывая лозунг "мир императивен". А всего то и надо, что понять — мир не императивен. Это модель мира, которая у тебя в голове, императивна.
Если принять за основу эту интерпретацию, то тараканы в голове не у нас
А всего то и надо, что оперировать фактами, а не вываливать собственное мнение о мотивах других людей под видом фактов.
VD>Увы и ах обоход то и дело выливается в кучу противоречий и проблем. Но мы внушаем себе что так и должно быть.
Пардон, где противоречия? Где проблемы?
VD>Нам говорят, что бошку можно сломать при попытке понять наши извращения.
Ну не можешь ты понять монады, ну бывает. Неприятно, что ты своё непонимание обращаешь в наше извращение.
Здравствуйте, VladD2, Вы писали:
VD>Блин, для особо упертых... Да, паттерн, но паттерн Хаскеля. В ООЯ ему просто нет места. Конечно его даже можно изобразить на ООЯ в которых поддерживаются функциональные объекты, но вот нужны в нем нет, так как есть другие подходы более естесвне6нные для этих языков.
Никто не говорил о нужде.
VD>Так нам будут показаны куски LINQ в которых используются монады?
Здравствуйте, VladD2, Вы писали:
L>>Я показывал общие свойства.
VD>Ничего ты не показал.
Влад, если тебе чего то непонятно, ты спрашивай
L>>Допустим, мы разрабатываем конкретную монаду в C#. Ну, предположим, у нас есть время поизвращаться. Дальше код условный, я на С# не пишу.
VD>Вот с этого надо и начинать было. "С# и занимаюсь гипотетическими рассуждениями...".
Ну тебе то незнание монад не мешает производить их оценку, верно?
Здравствуйте, Cyberax, Вы писали:
C>Ну да, С как и Perl может быть WOP-языком (Whatever Oriented Programming).
Не может. Мордой лица не вышел.
C>Просто тут был тезис, что ФП — это подмножество процедурного C>программирования. Я привел пример свойства, которым процедурное C>программирование не обладает, но которое необходимо для ФП. Вот и все.
Процедурному программированию по фигу есть ВФП или нет.
В некотором смысле процедурное программирование и функциональное конечно схожи. Однако процедурное программирование точно так же имеет много общего и с ООП.
В общем, ФП имеет множество своих паттернов. Для эффективного использования функционального стиля эти паттерны должны поддерживаться языком.
Я могу перечислить такие возможности:
1. Возможность производить все вычисления в виде выражений (ен стэйтментов). Это же позволяет обходится без именения состояния.
2. Возможность использовать рекрусию без ограничения.
3. Возможность манипулировать с функциями как со значениями. Эту возможность часто путают с ФВП. Меж тем ФВП есть малая толика того что подразумевается под данным пунктом. Например, функции нужно уметь помещать в списки и применять к спискам (в том числе и к спискам функций).
4. Иметь краткий синтаксис для объявления простых объектов (а ля POD в С++). Желательно, чтобы эти объекты поддерживали неизменяемость и полиморфизм.
5. Наличие сопоставления с образцом.
Все эти пункты желательны, но не за исключением первого и второго не обязательны. Современные ФЯ обладают всеми этими возможностями. Императивные языки поддерживают их ряд. C# поддерживает довольно гибкую работу с функциями, но все же не не совсем такую же чистую как в языках проектировавшихся для использования функционального стиля.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mirrorer, Вы писали:
M>ИМХО. Монады — это паттерн ФП. Я думаю что не единственный. Просто так сложилось что вокруг него больше всего непоняток возникает.. Почему — :xz:
Вот именно этот вопрос — переход от непоняткам к поняткам :-) мне кажется, надо решать исходя из конкретных задач (в этом смысле просмотр parsec'а хорошая идея).
Очень хорошо это сделано у Вадлера в The Essence of Functional Programming.
M>Тут +10 я тоже не очень понимаю почему именно этот интерфейс раскручивается..
В статье рассматривается задача построение интерпретатора, на который навешиваются различные свойства. Показывается, что применение монады делает подобную модификацию удивительно лёгкой. И всё это — следствие выделение интерфейса IMonad ;-)
Здравствуйте, VladD2, Вы писали:
VD>Но я так и не услышал разумного обяснения того зачем эту сущность не то что вводить в ООЯ, но даже употреблять для объясениях тех или иных концепций?
В общем лови. Часть статьи Вадлера "the essence of functional programming"
Суть какая. Пишется простейший интерпретатор. Типа того что ты приводил в каком-то посте про Nemerle. Потом к нему добавляется обработка ошибок. Потом к нему добавляется вывод позиции ошибки. Причем развитие делается с минимумом телодвижений. По возможности. И с объяснениями как бы это могло выглядеть без монад.
Мой поинт заключается в том, что монадную технику приводимую в статье можно с успехом использовать не только в Хаскеле. То есть код можно практически один в один преписать на Немерле и оно будет работать. Если есть способ написать аналог интерпертатора с меньшими телодвиженями — welcome.
Но еще раз повторюсь моя ИМХа заключается в том, что монадный подход можно использовать и вне Хаскела. Конечно многие веще можно сделать и без него. Но если монады в каком-то одном случае из сотни дадут выигрыш, то почему бы ими не воспольозваться?
Все кусочки готовы к уоптреблению. то есть их можно as is загрузить в интерпретатор Хаскела и поиграться. В последней части меня обломало приводить функции в более понятный вид. Если будет сильно уж непонятно — перепишу. пожелания замечания, этц велкам.
В этом сообщении будет описана база интерпретатора. Остальные части отдельными постами.
Комментарии и описание происходящего — в кмментариях к коду.
-- Имена переменных описываются строкойtype Name = String-- Термом может быть
-- Переменнаяdata Term = Var Name
-- Константа
| Constant Int-- Операция сложения
| Add Term Term
-- Лямбда
| Lambda Name Term
-- Операция вычисления
| Apply Term Term
-- Значением может быть
-- Ошибкаdata Value = Wrong
-- Число
| Num Int-- Функция (Functions are first class values :super:)
| Fun (Value -> M Value)
-- Environment - это переменные окружения, представленные списком пар (Имя, Значение)type Environment = [(Name, Value)]
-- Функция вывода значения
showVal :: Value -> String
showVal Wrong = "<wrong>"-- Для вывода числовых значений используется функция show из стандартной библиотеки Prelude
showVal (Num i) = show i
showVal (Fun f) = "function"-- Ключевая функция - интерпретатор.
interprete :: Term -> Environment -> M Value
-- Интерпретация значения переменной "x" сводится к поиску значения в переменных окружения
interprete (Var x) environment = searchFor x environment
-- Интерпретация константы производится путем возврата монадического значения числа.
-- то есть берем число "i" представляющее константу и запихиваем его в монаду при промощи функции
-- returnM имеющую тип a -> M a
interprete (Constant i) environment = returnM (Num i)
-- Интерпретация операции сложения. Запись более развернутая чем у Вадлера в целях упрощения понимания
-- удобнее рассматривать производящее с конца.
-- возьмем функцию add a b она вернет нам M Value согласно ее типу
-- то есть тип лямбды (\b -> add a b) будет Value -> M Value
-- поднимаемся на строчку выше и рассматриваем строку
-- bindM y_value (Value -> M Value)
-- поскольку bindM имеет тип M a -> (a - M b) -> M b
-- то y_value будет иметь тип M Value , поскольку такой тип у функции interprete, резульаттом работы которой и является y_value
-- а все выражение будет иметь тип bindM M Value (Value -> M Value)
-- то есть просто M Value, а значеним его будет M x+y , то есть сумма чисел x и у, будет внутри монады
-- После упрощения остается bindM x_value (\a -> M x+y)
-- значением лябмды будет M x+y, а ее типом - (Value -> M Value)
-- Следовательно результатом функции interprete (Add x y) е будет значение суммы x+y завернутое в монаду.
interprete (Add x y) environment = bindM x_value
(\a ->
bindM y_value
(\b -> add a b))
where
x_value = (interprete x environment)
y_value = (interprete y environment)
-- Интерпретация применения функции к аргументу. Абсолютно идентична Add x y_value
-- за исключеним того, что возвращаемым значением будет M apply a b
interprete (Apply function argument) environment = bindM function_value
(\a ->
bindM argument_value
(\b -> apply a b))
where
function_value = (interprete function environment)
argument_value = (interprete argument environment)
-- Интерпретация лямбды.
-- Значением выражения будет функция Fun
-- Согласно конструктору типа Fun принимает значение (Value -> M Value)
-- Проверим, так ли это. Расмотрим выражение (\a -> interprete v ((x,a):environment)) 3
-- подставив неопсредственно значение 3 в лямбду получим
-- interprete v ((x,3):environment)
-- таким образом зачением лямбды будет выражение v вычисленное в окружении, в котором х имеет непосредственно значение.
-- иначе говоря сначла мы добавляем в спиоск окружения новую переменную х, а потом вычилсяем значения лямбды
-- как interprete v new_environment, где new_environment = ((x,3):environment)
interprete (Lambda x v) environment = returnM (Fun (\a -> interprete v ((x,a) : environment)))
-- Функция поиска значения переменной в окружении
-- Классический рекурсивный проход по списку. Если значение найдено, возврщается монадическое значение переменной,
-- иначе Wrong
searchFor :: Name -> Environment -> M Value
-- Если добрались до конца спписка или окружение пусто - ошибка
searchFor x [] = returnM Wrong
-- Если имя "х" и имя первой пары в списке окружения "у" равны
searchFor x ((y,b) : environment) = if x ==y
-- то возвращаем значенеthen returnM b
-- иначе продолжим поиск в остальной части спискаelse searchFor x environment
-- Функция сложения
add :: Value -> Value -> M Value
-- если параметрами являются два числовых значения, то возвращаем монадическое значение их суммы
add (Num x) (Num y) = returnM (Num (x+y))
-- иначе возвращаем ошибку
add x y = returnM Wrong
-- Применение функции к аргументу
apply :: Value -> Value -> M Value
-- Если первый агрумент функция, то результатом будет применение функции f к аргументу а
apply (Fun function) argument = function argument
-- Иначе возвращаем ошибку
apply function argument = returnM Wrong
-- Функция test используется для вывода на экран значения терма.
test :: Term -> String-- Интерпретируем терм в пустом окружении, что даст на выходе M Value, и передаем результат в функцию
-- showM, которая имеет тип M Value -> String
test term = showM (interprete term [])
-- тестовый терм для проверки вычиления значения лябмда-выражения
-- (lambda x ( x + x))( 10 + 11) = 42
-- проверка производится в интерпретаторе Haskell путем вызова
--Main> test term0
--"42"
term0 = (Apply (Lambda "x" (Add (Var "x") (Var "x")))
(Add (Constant 10) (Constant 11)))
-- тест который должен возвратить значение типа "функция"
term1 = (Lambda "x" (Add (Var "x") (Var "x")))
Здравствуйте, Mirrorer, Вы писали:
M>Здравствуйте, BulatZiganshin, Вы писали:
BZ>>это вы рассужаете о своём паттерне. в моём примере использования монад речь шла о другом. есть универсальная процедура сериализации. куда сериализировать — она узнаёт из контекста вызова, т.е. из тех самых параметров. монады позволяют передавать эти паораметры неявно на всю глубину вызовов
M>То есть если я правильно понял, в данном случае аналогом в импетаривном языке будет дополнительный параметр у каждой процедуры по всей иерархии вызовов?
да. написанное вами — это монада Environment, позволяющая только читать обобществлённые данные. насчёт хеша же вы не совсем поняли. вы просто моджете передавать любую структуру данных, полиморфизм и вывод типов делает это так же возможным, как если бы вы написали специальный код
пример:
calculate = withState $ do
calc1
x <- calc2
y <- calc3
return (x++y)
calc1 = put (1, 2.3, "рояль")
calc2 = do (a,b,c) <- get
put (4, 5.6, " в кустах")
return c
calc3 = do (a,b,c) <- get
return c
вот это вычисление возвратит рояль в кустах при этом, хотя явно это не записано, фактически каждая операция получает эту триаду в качестве входного параметра и возвращзает её в качестве выходного. операция put заменяет старый state своим аргументом и возвращет () в качестве реузультат своего выполнения:
put param state = (param,())
операция get возвращает state в качестве результата своего выполнения и при этом, естественно, сохраняет сам state:
get state = (state,state)
остальные операции просто передают state дальше и дальше без изменений. все монадические операции, определяемые здесь — calc1/2/3 получают state в качестве дополнительного параметра и возвразают, помимо результата своей работы, новое состояние state, которое будет передано следующей операции в цепочке. скажем, расшугарив calculate, мы получим:
вот это уже монада State, котопая по принципам своего устройстьва напоминает IO. приведённая вами монада Environ,ent, которая подращзумевает только чтение входных данных, может обойтись без вохзвращения новго state из выполлняемых функций:
calculate = withEnvironment $ env ->
let _ = calc1 env
x = calc2 env
y = calc3 env
in (x++y)
как видите, в ней в монадические операции получают env в качестве входного параметра, но не возвразают его новое значение. дальше они также невидлимо передают его в качестве дополнительного параметра во все выхзываемые ими монадические операции
VD> Перечисление конечно по определению. А числа бесконечны.
Маленькая поправочка — в Хаскелле это не так.
Перечисление отдельно
class Enum a where
succ, pred :: a -> a
toEnum :: Int -> a
fromEnum :: a -> Int
enumFrom :: a -> [a] -- [n..]
enumFromThen :: a -> a -> [a] -- [n,n'..]
enumFromTo :: a -> a -> [a] -- [n..m]
enumFromThenTo :: a -> a -> a -> [a] -- [n,n'..m]
Здравствуйте, VladD2, Вы писали:
VD>Нет это их смысл. А вот области применения определяются этим смыслом.
Ну, кроме как посоветовать пойти почитать какие бывают монады мне больше нечего добавить.
VD>В общем, приведи плиз пример где в ООЯ были бы нужны монады.
Давай начну с отмазок — я не говорил, что они нужны в ООЯ, мало того, я даже не говорил, что они в ФЯ нужны :)
Но раз ты сказал волшебное слово...
Монады можно использовать, например, в качестве альтернативы известным паттернам проектирования. Например, вместо NullObject можно взять мейби-монаду. У этого подхода есть определенные преимущества перед NullObject (впрочем, как и недостатки). В частности, нам не нужен отдельный нуль-объект.
Да, и когда будешь отвечать на этот пример, вспомни, пожалуйста, что я не говорил, что монады "нужны", чтобы мы тут не нафлеймили (а то в последнее время у нас это здорово получается). Но вот обосновать их применение, наверное, можно. Раз уж люди их применяют.
Здравствуйте, VladD2, Вы писали:
VD>Уже читал. И весе применения в конце концов приводят к последователному изменению состояния, т.е. императиву.
Некоторые монады вовсе не предназначены для изменения состояния.
Некоторые не предназначены для последовательного исполнения.
Простой пример — монада списка.
L>>Давай начну с отмазок — я не говорил, что они нужны в ООЯ, мало того, я даже не говорил, что они в ФЯ нужны :)
VD>Но полез защищать ахинею о том, что в ООЯ что-то там реализовано на монадах?
Ну, если на самом деле интересна моя мотивация, то она примерно такова.
Ты назвал человека некомпетентным, теперь называешь его мнение ахинеей. Я так не считаю, так почему бы не вложить свои 5 копеек?
L>>Монады можно использовать, например, в качестве альтернативы известным паттернам проектирования. Например, вместо NullObject можно взять мейби-монаду. У этого подхода есть определенные преимущества перед NullObject (впрочем, как и недостатки). В частности, нам не нужен отдельный нуль-объект.
VD>Изивини, но почему в ОКамл и Немрле есть аналогичные решения без монад? Поместил объект в Some(...) и пользуйся, а если нужно извлечь, то паттерн матчинг к твоим услугам.
Тут может быть много ответов. Но все они поведут к флейму. Я попытался обощить ниже.
L>>Да, и когда будешь отвечать на этот пример, вспомни, пожалуйста, что я не говорил, что монады "нужны", чтобы мы тут не нафлеймили (а то в последнее время у нас это здорово получается). Но вот обосновать их применение, наверное, можно. Раз уж люди их применяют.
VD>Я вижу, что ты понимашь это. Но я так же вижу, что когда кто-то неразобравшись в вопросе понес ахинею, ты помог ему закрепить его заблуждения.
Попробую донести свою мысль. Всё нижеследующее — это моё имхо. Монады — абстрактное понятие. В том смысле, что это гораздо абстрактнее понятия конкретного паттерна. Вот когда я описывал альтернативу для NullObject — я взял конкретную монаду. Т.е. говорить об использовании монады без указания конкретной монады, это почти как говорить об использовании паттерна без указания конкретного. "Почти" — потому что польза от этого всё таки есть. В силу того, что все они подчиняются определенным правилам, т.е. понятие достаточно формализовано.
Для того, чтобы на некоторое решение можно было бы взглянуть как на монадическое, достаточно, чтобы это решение соотвествовало нескольким правилам. Если эти правила соблюдаются, то, оперируя понятием монады, мы можем вывести некоторые свойства этого решения. А так — какая разница как называть это решение — монадой или нет — по барабану. Именно поэтому я считаю вопрос о нужности/ненужности монад бессмысленным.
Резюмируя (я тут в параллельных ветках твои ответы почитал). Разница в понимании монад у нас, видимо, следующая — для меня монада, это всего лишь интерфейс. Если его объявить явно, то мы поимеем унификацию всех монад, например, сможем иметь общие фунции над монадами, вместо того, чтобы писать для каждой свою. Если не объявлять — мы все равно можем заметить этот интерфейс, если он есть. И сделать для себя определенные выводы. Для тебя монада — это исключительно IO/State, которые, действительно, эмулируют императив. Эти монады в ИЯ не нужны.
Здравствуйте, LaPerouse, Вы писали:
LP>Повторяю — функциональное программирование является разновидностью процедурного, нравится вам это или нет. Единственное отличие заключается в подходе к хранению состояния. Если задаться целью, можно и на С писать почти в функциональном стиле. Разница между императивным и функциональным программированием мне понятна, что и позволило мне прийти к такому умозаключению.
Не является функциональное программирование разновидностью процедурного, нравится вам это или нет.
Объяснения по поводу того, что можно писать на С переадресуйте любителям С++. Я, например, знаю, что многие прекрасно пишут в объектно-ориентированном стиле на С и не жалуются. Тот факт, что на С можно, хоть и через Ж, писать в любом стиле, ничего не означает.
Hello, Cyberax!
You wrote on Wed, 31 Jan 2007 22:24:10 GMT:
>> Повторяю — функциональное программирование является >> разновидностью процедурного, нравится вам это или нет. C> Да даже близко не является. Процедурное программирование — это C> подмножество императивного стиля.
C> Функциональное программирование — это совершенно другой стиль. C> Ортональный ООП и противоположный императивному.
Думаю, вы не сможете договориться даже насчет определения функционального и процедурного программирования, не говоря уже о чем-то большем.
Долго думал, встрявать или нет.
Встряну!
LP>Все-таки основным критерием функционального подхода является то, о чем я говорил выше – отношение к хранению состояния. Вот он, постамент, на котором зиждется вся теория и практика функционального программирования, тот самый “пятый элемент”, придающий особый колорит этому стилю. Стоит только разрешить изменение переменных в любом “функциональном языке” и внешние ссылки на эти переменные (которое не нужно даже специальным образом вводить), и этот язык неуловимо для глаз превратится в стандартный процедурный язык.
Стоит в литр воды насыпать щепотку соли, и она станет непригодной для питья.
По делу: неизменяемые состояния — следствие. Основа — чистота функций. Если любая функция при одних и тех же входных параметрах возвращает одно и то же, то это настоящий (чистый) функциональный язык. Это требование — необходимая и достаточная гарантия для большинства техник, составляющих функциональное программирование. А изменяемые состояния, если они нужны, можно при этом эмулировать, скажем в Хаскелле с помощью монады State.
Я не очень хочу флеймить по этому поводу, отсылаю жаждущих подробностей или драк к книжке Филд, Харрисон Функциональное программирование, М., Мир, 1993 г. Там во введении всё написано довольно подробно. У Мошкова версия битая (была, по крайней мере, полгода назад), но где-то в сети была и хорошая (google поможет).
И Остап протянул Ухудшанскому лист, на котором было
написано: ТОРЖЕСТВЕННЫЙ КОМПЛЕКТ НЕЗАМЕНИМОЕ ПОСОБИЕ ДЛЯ СОЧИНЕНИЯ ЮБИЛЕЙНЫХ СТАТЕЙ, ТАБЕЛЬНЫХ ФЕЛЬЕТОНОВ, А ТАКЖЕ ПАРАДНЫХ СТИХОТВОРЕНИЙ. ОД И ТРОПАРЕЙ.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Mamut, Вы писали:
M>>Lisp (хоть он и не является ФЯ, как таковым)
VD>Сколько раз я уже слышал это глубочайшее заблуждение. Откуда вы берете это ерись?
Это не ересь, это правда лисп настолько же функциональный насколько и императивный.
VD>Лисп прородитель всех ФЯ. В нем концепции ФЯ были сормированы и опробированы. Все ФЯ клоны лиспа в некотором смысле.
Это не мешает ему одновременно быть и императивным.
GlebZ wrote: > FR>Это не ересь, это правда лисп настолько же функциональный насколько и > императивный. > Там есть оператор goto или цикл?
Есть там цикл (loop). Многофункциональный, даже слишком.
Здравствуйте, lomeo, Вы писали:
L>Изобретаем IO-монаду?
Какая такая IO-манда? Это же Algol-48. Язык, который (по мнению Маккарти) математики создали бы в 1948, если бы требовалось что либо помимо машинного языка.
Программа на Algol-60
0 start: p := 0;
1 i := n;
2 loop: if i = 0 then go to done;
3 p := p + m;
4 i := i - 1;
5 go to loop;
6 done:
Эта же программа на Algol-48
p(t+1) = if pc(t) = 0 then 0
else if pc(t) = 3 then p(t) + m
else p(t),
i(t+1) = if pc(t) = 1 then n
else if pc(t) = 4 then i(t) - 1
else i(t),
pc(t+1) = if pc(t) = 2 & i(t) = 0 then 6
else if pc(t) = 5 then 2
else p(t) + 1.
Здравствуйте, VladD2, Вы писали:
EC>>Интересно, с выходом LINQ твоё мнение изменится на прямо противоположное? EC>>Хинт. EC>>Заметь, этим занимается знатный хаскелист Erik Meijer, такой попсовой штукой как VB и LINQ.
VD>Причем тут LINQ и VB? Ты хоть разберись о чем люди говорят, а потом влезай.
LINQ это монады для мейнстрима.
now playing: Boards of Canada — An Eagle In Your Mind
Здравствуйте, EvilChild, Вы писали:
EC>LINQ это монады для мейнстрима.
Я даже не знаю что моно ответить на подобную некомпетентность.
Монады — это способ организовать последовательные императивные вычисления в чисто-функциональном и ленивом языке.
Ленивый — хначит позволяющий вычислять выражения не в определенной программистом последовательности, а по мере необходиомсти.
C# не является линивым, и является императивным. В нем вычисления и так импереативныи и последоательны. Монады ему ныжны как рыбе зонтик.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Монады — это способ организовать последовательные императивные вычисления в чисто-функциональном и ленивом языке. VD>Ленивый — хначит позволяющий вычислять выражения не в определенной программистом последовательности, а по мере необходиомсти.
VD>C# не является линивым, и является императивным. В нем вычисления и так импереативныи и последоательны. Монады ему ныжны как рыбе зонтик.
не совсем так. использование монад для создания императивного кода — лишь одно из их применений. принципиально, монада — это некий контекст, в котором производятся вычисления. этот контекст может быть, например, текущими обрабатываемыми данными, сообщением об ошибке или выходными данными. без монад это всё нужно передавать либо явными параметрами, либо хранить в глобальных переменных. первое многословно и разрушает абстракцию, второе — бад стайл, и бесполезно при многопоточном программировании
ещё одна идея, которая к С++ видимо тоже неприменима — ST монада позволяет писать императивный код, результат которого можно использовать в pure вычислениях (это гарантировано самим устройством этой монады). в C++ это можно реализовать только на уровне специальной компиляторной оптимизации, которая будет сообрадать, какие функции pure, а какие — нет
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, lomeo, Вы писали:
L>>Нет. Это всего лишь одна из областей их применения. L>>В LINQ используется не она.
VD>И что используется в LINQ?
Erik Meijer пишет, что query monad, как в HaskellDB, над которым, кстати, он работал.
SelectMany == bind, имхо, остальные операторы тоже представляют собой монадические комбинаторы.
Здравствуйте, 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)
Здравствуйте, AndrewVK, Вы писали:
VD>>Не, скорее паттерн "передача объекта через параметр метода".
AVK>Нет. Передавать через параметры плохая идея. Сервисы появляются и умирают, зачастую динамически. Править каждый раз всю цепочку вызовов плохая идея.
Ты просто пришел с тем что тебя волнует. А то что обсуждается к этому отношения не имеет. Твои "сервисы" не более чем развитие идеи "супер навороченной глобальной переменной", а товарищи обсуждаеют передачу объекта через параметр. Понимаешь ли в чем дело, у этих товарищей бльшие проблемы как с наличием самого объекта, так и с возможностью изменения его состояния в нужной последовательнсоти. У них все вычисления чистые. Так что когда им надо тупо передать объект или изменить его состояние, то они вынуждные изобретать нечто под названием "хреновина", тфу ты, "монада", чтобы сделать вид, что они всего лишь трахнулись на стороне, а не изменили любимой.
Вот такие пироги с катятами. Но с глобальными переменными и уж тембоее с динамически подключаемыми сервисами у них проблем еще больще. Так что тут тоже будут хреновины... тфу ты монады.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Блин, ну неужели трудно понять, что 90% здоровых на голву людей бросят сам язык когда дойдут до этого самого лифтинга. Это все равно что заливать в перегретый автомабиль воду из кипящего чайника!
а это не для начинающих для начала удобно как раз считать, что в хаскеле есть императивный и функциональный подязыки. я даже собирался написать "introduction to IO" в этом ключе, без всяких упоминаний о монадах. может, напишу его на русском
VD>И все это ради того чтобы не признать правды — мир императивен и "чистоту" надо просто отделять от "императивной грязи".
я не зря привёл пример с Ньютоном — он тоже отказался признавать, что планеты просто вращаются по эллиптическим орбитам и развёл целый мааппарат, позволяющий свести это к закону притяжения. всё это — лишь концепции. можно было сделать хаскелл двухконцептным языком, введя в него особые правила для записи императивных программ, их трансляции, оптимизации и т.д. а можно было — пользуясь средствами языка, выразить императивное программирование через функции, "преобразующие мир". при этом язык не раздулся как покойник и весь уже наработанный аппарат компиляторов спокойно работает с новой концепцией как частным случаем старой. ортогональность — это ключ к созданию хороших языков. "усложнять просто, упрощать — сложно"
VD>Эта концепция проста для понимания.
всякая концепция, которую ты уже понял, кажется простой для понимания скажем, я считаю функциональный подход более естественным и простым для понимания, нежели императивный и для меня такая программа:
fac 0 = 1
fac 1 = n * fac(n-1)
выглядит простой и ясной. а большинству людей, обученных императивному программированию, удобней и понятней запись в виде цикла. третьи же предпочитают higher-order funcs и запишут это в виде:
Здравствуйте, BulatZiganshin, Вы писали:
BZ>а это не для начинающих для начала удобно как раз считать, что в хаскеле есть императивный и функциональный подязыки. я даже собирался написать "introduction to IO" в этом ключе, без всяких упоминаний о монадах. может, напишу его на русском
Это хорошее начинание. Только сильно запоздалое.
VD>>И все это ради того чтобы не признать правды — мир императивен и "чистоту" надо просто отделять от "императивной грязи".
BZ>я не зря привёл пример с Ньютоном — он тоже отказался признавать, что планеты просто вращаются по эллиптическим орбитам и развёл целый мааппарат, позволяющий свести это к закону притяжения. всё это — лишь концепции. можно было сделать хаскелл двухконцептным языком, введя в него особые правила для записи императивных программ, их трансляции, оптимизации и т.д. а можно было — пользуясь средствами языка, выразить императивное программирование через функции, "преобразующие мир". при этом язык не раздулся как покойник и весь уже наработанный аппарат компиляторов спокойно работает с новой концепцией как частным случаем старой. ортогональность — это ключ к созданию хороших языков. "усложнять просто, упрощать — сложно"
Я знаю одно. Сложность восприятия это крышка гроба для любого языка.
Вообще, мне кажется мы подходим к точки в истории разития языков когда в список обязательных будут влючаться не только то что влючалось по сей день, но и простота, интуитивность, возможность создания для языка качественной IDE и многие другие "потребительские свойства" на которые забивают большинство исследователей.
VD>>Эта концепция проста для понимания.
BZ>всякая концепция, которую ты уже понял, кажется простой для понимания скажем, я считаю функциональный подход более естественным и простым для понимания, нежели императивный
У нас разный подход. Ты говоришь о том, что тебе кажется, а я о том, за чем наблюдал. Мое мнение о простоте и интуитивности основано на наблдении за тем как настоящие новички воспринимают новый язык. Плюс еще одно. Я работаю редактором и в мои обязанности входит выискивать в статьях места которые будут непонятны читателям. И я без ложной скромности скажу, что приуспел в этом. Так вот я довольно быстро могу оценить что то или иное изложение будет непонятно аудитории. Так вот недавно я как раз вычитывал введение в Хаскель и сделал однозначный вывод, что до конца его дочитают только самые стойкие. И это еще очень неплохой варинат. Все что я видел до этого было еще хуже. Причем учти, что я сделал этот вывод прекрасно понимая концепции ФП.
BZ>и для меня такая программа: BZ>
BZ>fac 0 = 1
BZ>fac 1 = n * fac(n-1)
BZ>
BZ>выглядит простой и ясной.
Это детские примеры.
fac(int n)
{
if (n == 0)
return 1;
else
return n * fac(n - 1);
}
это булшит которым пичкуают читателей во всех трудах прославляющих ФП. Но читатель то может и оглох, но не охринел. Он может не всилах понять написанного, но тонко чувствет обман. Ведь когда он видит сложную программу на ФП, то она превращаетя в кашу птичек.
BZ> а большинству людей, обученных императивному программированию, удобней и понятней запись в виде цикла. третьи же предпочитают higher-order funcs и запишут это в виде:
BZ>
BZ>fac n = foldr (*) [1..n]
BZ>
Вот, вот. И при том объяснении которое дают бльшинство книг и статей по ФП никто из новичков не поймет написанного. Растрою тебя, то тут не наберется и десятка прочевших это сообщение кто полностью поняд как эта штука работает.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Кроме слова "бред" у меня других оценок не находится.
Слова "query monad, как в HaskellDB, над которым, кстати, он работал" вообще каша какая-то. Какое отношение "query monad" из HaskellDB имеет к C#. И какое отношение между сравнением чего-то с чем-то из другого языка имеет к наличию этого в другом языке? И соттвественно оправданию лозунгов вроде "LINQ это монады для мейнстрима."?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
AVK>Про ужасную сложность передачи логгера внутрь кода без монад не я рассказывать начал, так что притензии не ко мне. У меня с логгером никогда никаких проблем не было.
Я тебе еще раз повторяю, что у они себе сами объясняют как боросться с тараканами которых они сами же запустили в свою голову.
Люди принимают догмат "чистоты", но сразу же придумывают другой догамт позволяющий эту чистоту обойти. Казалось бы так все просто. В ФЯ любая функция при одном наборе аргументов обязана вернуть один определенный результат. Это помогает во многих случаях. Там распраллеливание, простота отладки, и еще много чего, но вот увы это не вяжется с реальным миром. В любом ООЯ мы просто создали бы объект в который положили бы ссылку на перменную или, как это предлагаешь ты, на хитрый объект сервис-локатор, но увы у нас догмы. Мы не может это сделать. Тогда мы придумываем хитрую чтоуку называем ее поумнее и вуаля обходим наши же ограничения.
Увы и ах обоход то и дело выливается в кучу противоречий и проблем. Но мы внушаем себе что так и должно быть.
Нам говорят, что бошку можно сломать при попытке понять наши извращения. И мы знаем есть куда более простые сущьности повзоляющие решать проблемы. Они понятны и логичны. Но не в наших правиалх выбирать простые пути. Мы борцы за идею. Идею чистоты. Даешь девственность даже путем операции.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Bulat,
BZ>что же касается концепции монад, это это уже было обобщение этого паттерна, использование его в других областях. на данный момент можно сказать, что монады — это стратегия вычислений, определяемая отдельно от самих этих вычислений
Ну что же, спасибо. Наконец, я получил наиболее полный ответ на мой вопрос про
Здравствуйте, lomeo, Вы писали:
L>Почему опять трудится должен я? Потрудись перечитать мой ответ. Что тебе в нём непонятно?
Вступлюсь: мне тоже непонятно. Тридцать постингов назад ты взял на себя смелость процитировать высказывание неизвестного мне авторитета, которое по силе можно лишь сравнить с "горчица — это масло для бедных". Мы тут все развесили уши в ожидании того, как ты раскроешь нам тайны бытия и проиллюстрируешь взаимосвязь Linq и монад. А ты уже чуть не неделю ведешь себя как гимназистка на свидании: "я это не буду объяснять, я уже всё объяснилав прошлый раз", "если ты до сих пор не понял, то сам же и виноват", "у меня нет другого объяснения, кроме того, которое ты проигнорировал" и прочий лепет в том же духе.
Тебе что, и вправду непонятно, что именно в приведенном рекламном лозунге вызывает недоумение? Обычно, когда люди говорят, что-то вроде "кошка похожа на собаку", им не очень трудно пояснить, что у них есть какие-то общие свойства. К примеру, что и кошек и у собак есть хвост.
Вот мне, к примеру, жутко интересно, что общего у Linq и монад. Мое несовершенное понимаение монад сводится к чему-то вроде "способ управлять композицией функций". В Linq ничего похожего на управление способом композиции функций нет.
Вот что такое Linq:
1. Extension Methods (жизненно важны для того, чтобы запросы могли работать по любым коллекциям, в том числе и самым абстрактным)
2. Lambda Functions (без них запись предикатов получается слишком громоздкой, фактически это сахар для анонимных делегатов)
3. Еще раз Lambda Functions — на этот раз в виде поддержимого компилятором переноса информации из Compile-Time в RunTime. Это совершенно ортогональная предыдущему пункту штука. Сам по себе Linq может работать и без нее, но не будут работать биндинги к удаленным источникам данных типа DLinq.
4. Анонимные типы. Аналогично анонимным делегатам, помогает избавиться от мусорного кода по декларированию временных структур только для того, чтобы передать данные от одного фрагмента запроса к другому.
5. Спец.синтаксис для SQL-Like запросов. Совершеннейший сахар; ничего особенного не дает.
Из этого списка сходство с возможностями монад имеет только п.4, и то это весьма отдаленное сходство. Если ты так хорошо понимаешь суть сходства Linq и монад, тебе не составит труда кратко обозначить, какие из перечисленных мной возможностей связывают между собой эти понятия. Не отвечая вопросом на вопрос и не ссылаясь на ссылки на цитаты. А?
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, lomeo, Вы писали: L>Я показывал общие свойства.
Я не видел.
L>Наверное, на монаду можно смотреть по разному. Как и на любой достаточно абстрактный предмет. L>Здесь твой взгляд ничем нам не поможет, и поэтому я вынужден провести маленький ликбез. Извини, если говорю прописные для тебя истины, но он нам нужен, чтобы у нас была общая база для обсуждений.
Нет, как раз ликбез я и хотел! L>Итак у монад есть основные свойства. В частности, это операция bind, связывающая монаду с вычислением над её значением.
L>bind имеет тип m a -> (a -> m b) -> m b. Это означает, что мы можем взять одну монаду и (здесь важно!) функцию, которая принимает значение типа значения из монады (a) и возвращает новую монаду. Таким образом мы, работая с функциями над значениями, связываем монады над этими значениями. Это очень полезное свойство, позволяющее прятать стратегию этой связки.
Ну, это вроде бы понятно. Вот она наша абстрактная монада.
L>Допустим, мы разрабатываем конкретную монаду в C#.
О, давай разработаем. L>Ну, предположим, у нас есть время поизвращаться. Дальше код условный, я на С# не пишу.
Заранее скажу, что код вполне понятный. L>В качестве монады мы берём тип IEnumerable<T>. Значит, функции, подверженные связке будут иметь тип что то вроде IEnumerable<B> foo<A,B>(A x). Ну A и B могут быть одними и теми же. Назовем этот тип Foo. Его можно сделать делегатом. Bind будет иметь тип IEnumerable<B> Bind<A,B>(IEnumerable<A> m, Foo<A,B> f). Семантика простая — для каждого значения A из m зовем f, потом всё склеиваем в новый IEnumerable. Ну и пусть она будет extension методом.
Прекрасно. Что-то подобное я использовал в своей практике. L>Теперь мы можем получить что то вроде m.Bind(Do1).Bind(Do2)...
Ага, можем. Хоть пока и непонятно, зачем. В принципе, я сейчас использую такие штуки.
L>Обратим внимание на два момента — первое — в C# Bind надо писать явно и второе — функций DoX у нас по задаче ограниченное количество — Where, Select и т.д., поэтому его можно вшить в функции Bind_DoX, а саму эту функцию сделать по аналогии с функцией update — простая задача обощения.
L>Вот и всё. От монад мы легко пришли к LINQ — я показал, что у них есть общего?
Неа. Ничего особенно общего тут нет. Либо монады — это что-то такое супервсеобщее, либо я чего-то не понимаю. То есть я понимаю, что если бы мы писали Linq на хаскеле, то скорее всего обошлись бы монадой. Но в Linq никакими монадами и не пахнет. Тот bind, о котором ты упоминаешь, вроде бы должен быть за сценой. Но в Linq его спрятать нельзя — потому что это может быть как extension method, действительно применяющий этот Foo к каждому из m. А может быть нормальный метод класса, который принимает Expression и на его основе собирает SQL для отправки на сервер. Может быть, аналог такого тоже можно изобразить в виде монады на функциональном языке. Но это уже скорее из области доказательства взаимной эквивалентности машины Тьюринга и частично-рекурсивных функций.
Что меня настораживает — это то, что ты начинаешь с функции bind, являющейся частью определения монады, а потом убеждаешь нас, что эта функция есть в Linq, хотя ее там нету. Но могла была бы быть, если бы Linq был на другом языке и с другими правилами.
L>Я это сделал ещё в том своём посте. В этом всего лишь разжевал.
Тебя просили разжевать очень-очень много раз.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
L>>Теперь мы можем получить что то вроде m.Bind(Do1).Bind(Do2)...
S>Ага, можем. Хоть пока и непонятно, зачем. В принципе, я сейчас использую такие штуки.
Но ведь каждый думает по своему, когда решает какую то задачу. Монада — это паттерн, решающий задачу. Допустим, мы идём от него — мы же хотим выяснить связь?
L>>Вот и всё. От монад мы легко пришли к LINQ — я показал, что у них есть общего?
S>Неа. Ничего особенно общего тут нет. Либо монады — это что-то такое супервсеобщее, либо я чего-то не понимаю.
Да, ты почти прав. Монады — это интерфейс. Явно мы его здесь не используем, но аналогию проследить можно.
S>Что меня настораживает — это то, что ты начинаешь с функции bind, являющейся частью определения монады, а потом убеждаешь нас, что эта функция есть в Linq, хотя ее там нету. Но могла была бы быть, если бы Linq был на другом языке и с другими правилами.
Я как раз пытаюсь объяснить, что монада — вещь слишком общая для того, чтобы быть принадлежностью языка. Вот смотрю я на код на Хаскеле и говорю: Ба! Да это же Визитор. Мне говорят, чувак, ты чего? Тут же ФВП для обхода используется + паттерн матчинг. В этом языке вообще объектов нет.
Ну, что ж. Визитор зафиксирован на объектах, может быть они и правы. Но монады зафиксированы только на свойствах естественных преобразований над ними. Эти преобразования можно проецировать на функции, на части функции, на объекты, на их кусочки — на что твоей душе угодно. И потом ты с этим можешь работать как с обычными монадами.
Например, показав, что запрос в LINQ является монадой мы можем быть уверены (т.к. это доказано на более общем уровне), что m.Select(x => x) == m или то же самое с SelectMany. Что x.SelectMany(f).SelectMany(g) == x.SelectMany(x => f(x).SelectMany(g)) ну и так далее.
Я понимаю, что это практикующему программисту не нужно но от этого он вряд ли лишается права глядеть на LINQ как на монаду.
L>>Я это сделал ещё в том своём посте. В этом всего лишь разжевал.
S>Тебя просили разжевать очень-очень много раз.
Здравствуйте, lomeo, Вы писали: L>Например, показав, что запрос в LINQ является монадой мы можем быть уверены (т.к. это доказано на более общем уровне), что m.Select(x => x) == m или то же самое с SelectMany. Что x.SelectMany(f).SelectMany(g) == x.SelectMany(x => f(x).SelectMany(g)) ну и так далее.
О, вот это уже интересно. А можно продемонстрировать путь такого доказательства? Я правильно понимаю, что для него нам понадобится умение выполнять из Select(IEnumerable<T> this, Predicate<T> predicate) декомпозицию в Bind и что-то еще, а потом анализировать свойства этого чего-то еще?
L>Я понимаю, что это практикующему программисту не нужно но от этого он вряд ли лишается права глядеть на LINQ как на монаду.
Нет, я все это понимаю, и уметь увидеть в вызове процедуры на паскале композицию кортежа — очень полезно для развития воображения. Но мне кажется, что роль монад в Linq сильно преувеличена. Под определенным углом можно увидеть почти все что угодно во всем, что угодно. C некоторой точки зрения оператор switch, виртуальные методы, и обработчики исключений можно рассматривать как частные случаи паттерн-матчинга. Но особенной ценности это рассмотрение нам не даст, особенно если учесть, что вторые и третьи были придуманы во многом для того, чтобы избавиться от первого.
L>Но только ты показал, что именно не понятно
Ну, я наверное умею тупить наиболее убедительно
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>О, вот это уже интересно. А можно продемонстрировать путь такого доказательства? Я правильно понимаю, что для него нам понадобится умение выполнять из Select(IEnumerable<T> this, Predicate<T> predicate) декомпозицию в Bind и что-то еще, а потом анализировать свойства этого чего-то еще?
Да правильно понимаешь. Для SelectMany я думаю всё понятно. Для Select(x => y) надо показать, что он аналогичен SelectMany(x => {y}), где {y} — конструирование нового IEnumerable над одним элементом.
L>>Я понимаю, что это практикующему программисту не нужно но от этого он вряд ли лишается права глядеть на LINQ как на монаду. S>Нет, я все это понимаю, и уметь увидеть в вызове процедуры на паскале композицию кортежа — очень полезно для развития воображения. Но мне кажется, что роль монад в Linq сильно преувеличена. Под определенным углом можно увидеть почти все что угодно во всем, что угодно.
Ты прав.
В своё оправдание лишь скажу, что как минимум, я показал, как с помощью этого паттерна можно легко придти к решению задачи. Разве это не является практической ценностью?
S>C некоторой точки зрения оператор switch, виртуальные методы, и обработчики исключений можно рассматривать как частные случаи паттерн-матчинга. Но особенной ценности это рассмотрение нам не даст, особенно если учесть, что вторые и третьи были придуманы во многом для того, чтобы избавиться от первого.
Здравствуйте, VladD2, Вы писали:
VD>Ты мня извини, но прежде чем кидаться что-то объяснять можно спросить у того кому собрался объяснять, а "не знает ли он этого?". Так вот отвечу — знаю. Но ленивость и чистота в Хаскеле ваимозависимые вещи. Желание сделать весь код линивым вынуждает делать его чистым, а полная чистота требует ленивости. Монады же призваны обходить оба ограничения делая вычисления последовательными и модифицирующими в казалось бы чисто-фукнциональном языке. Другими словами они эмулируют то что в других языках есть штатно: императивность и объектную ориентацию.
Твоя ошибка в том, что чистота не требует ленивости. Ленивость — это оптимизация. Она может быть ручной(ML но не уверен), может быть автоматической (FPTL) либо постоянной как в Хаскель. Ленивость не есть свойство чистого функционального языка. Оно лишь оптимизирует конечный код.
Мне Хаскель (который я пока только подгрызываю в силу недостатка времени) интересен именно как лаборатория. Ты в первую очередь обращаешь на средства предоставляемые пользователю. Мне интересно, как из декларативщины получает эффективный императивный код. И тут в чистоте просто огромные возможности и потенциал. В чистом языке функция — это команда компилятору но не более того. В реальном коде функции просто уже не будет существовать в силу трансформации всех уравнений компилятором. Компилятор здесь может это себе позволить. В императиве инлайнинг — это детский лепет. Это больше похоже на SQL. Уже давно никто не исполняет команды записанные программистом. Выполняются эффективный граф команд полученный оптимизатором.
Здравствуйте, Mirrorer, Вы писали:
VD>>К сожалению не всегда все очевидно m, a, s и т.п. просто сбивают с толка. M>Эх.. Да, жаль сообщения редактировать нельзя.. Подправил бы. Но в целом не так уж важно.
Это хороший пример, почему на rsdn польтзователям нельзя редактировать сообщения. Ну подправил бы ты. А письмо Влада осталось. И кто потом это бы прочел, долго бы удивлялся о чем идет речь.
Sinclair wrote: > C>Функторы — элементарно: > C>//Суть понятна? > Неа. Непонятна. Покажи мне какой-нибудь другой функтор, который можно > передать в Reduce.
struct EnhancedFunctor
{
struct Functor base; //Трюк с наследованиемint threshold;
};
int sumNumbersGreaterThan(Functor *self, int a, int b)
{
EnhancedFunctor *enh=(EnhancedFunctor*)self; //!!if (a>enh->threshold) return b;
return b+a;
}
//Наш конструктор
Functor * new_filtering_functor(int threshold)
{
EnhancedFunctor *f=(EnhancedFunctor*)malloc(sizeof(Functor));
f->base.func=&sumNumbersGreaterThan;
f->threshold=threshold;
return f;
}
//Немного модифицируем reduce:int reduce(List *lst, Functor *f)
{
int res=0;
while(lst!=null)
{
res=f->func(f, lst->data,res); //Добавим указатель 'this'
lst=lst->next;
}
return res;
}
...
Functor *filter=new_filtering_functor(11);
int res=reduce(some_list, filter);
Такой трюк с наследованием структур гарантировано будет работать по
Стандарту С. Собственно, он очень широко используется в GTK. Там,
кстати, я такие трюки и видел.
Показать еще пару аналогичных функуторов?
Если еще добавить базовый класс с тремя двумя указателями на функции
(QueryInterface, Release, Add), то можно построить аналог COMа.
> C>Точно так же делаем bind_1st/bind_2nd. > Пока не понимаю, как именно
Если честно, мне не хочется вспоминать синтаксис указателей на функции
из C, а то бы написал
Здравствуйте, Andir, Вы писали:
A>Ну так сразу в научные статьи лезть я не хочу Страшно Конкретика от товарищей уже поинтересовавшихся темой интересна.
К сожалению, не могу особо чем-то помочь. Интерес чисто платонический, и соответвенно знания только те, которые случайно встретились. Все статьи по оптимизации — научные. Особенно для функциональных. Каждый пытается не только описать некоторую оптимизацию, но и доказать.
В основном используется компинаторная алгебра (лябда исчисление) и теория графов. Без этих знаний — ни фига ничего непонятно. Еще похоже нужна теория категорий.
Вообще же, люблю бегать по citeseer. Там есть например такой раздел Top:Programming: Functional И вообще система ссылок — достаточно эффективная. Весьма простой для прочтения показалась эта статья. Еще посмотри в Clean они описывали Graph Rewrite. Интересная фенька. Лень ссылку искать, у них на сайте в описании языка было краткое описание.
ну вот и на C монады реализовали
M>В качестве примера рекурсии часто используется вычисление факториала. Но без tail оптимизации оно значительно менее эффективно чем императивное решение в лоб. Однако это не значит что сама идея рекурсии ущербна. Да, если реализовывать фаткориал в лоб, ничего хорошего не получится. Но ведь рекурсию еще можно применить в куче разных мест. Точно так же и с монадами. Ввод вывод в Хаскеле мне самому не шибко нравится. Он мне непривычен. Но та же монада List весьма интересная штука.
самое красивое применение монад — parsec и люббые другие parsing combinators. там они используются для бэктрекинга при неудачном разборе, т.е. запросто можно запистать что-то вроде:
что касается в/в — то читай http://haskell.org/haskellwiki/IO_inside . то, что императивные операторы в хаскеле — частный случай обычных функций, даёт возможность применять к ним весь арсенал higher-order funcs. там как раз приводятся примеры того, как императивные процедуры хранятся в списках, передаются туда-сюда, частично применяются и тому подобное. только что я приводил пример их композиции в виде отдельно запускаемых тредов. у меня в программе вообще куча универсальных управляющих конструкций и просто по месту определяются процедуры, которые скажем файлы после обработки подчищают. т.е. использование процедур как first-class objects позволяет лучше структурировать программу
Здравствуйте, VladD2, Вы писали:
L>>Увы, почему то монады сложны для первоначального понимания (тяжело врубиться, грокнуть). Хотя по сути они просты.
VD>Ну, слава богу хоть один из прверженцев пуризма признал этот проской казалось бы факт.
Грязнули наступают?
Кто то здесь говорил, что врубился в монады первый же день? Потом, я не считаю сложность вхождения в язык большой проблемой. Причина проста — я не очень то нуждаюсь в том, чтобы Хаскель стал мейнстримом. А применяю я их очень просто и естественно. Они меня совершенно не напрягают.
VD>А можно ли выразить нужные концепции в языке другими, более легкими для понимания сущьностями?
Если мы говорим об IO/State монаде, то для этого были предложены такие способы, как потоки и продолжения. К сожалению, это слишком частные решение. Они решают только проблему последовательного исполнения, в то время как монада (вообще, а не IO) — более общую. Таким образом, эти способы не могут решить проблемы, которые решают другие монады. Аналог монад — комонады более просты для понимания, и на них тоже можно сделать IO и многое другое (например, Richard B. Kieburtz — Codata and Comonads in Haskell). В реализации, правда, чуть сложнее (правда, это имхо).
Если же под более легкими для понимания сущностями ты имеешь внесение в язык явного императива, то это мы с тобой уже обсуждали: это (минимум) вопросы целей, и цели авторов языка могут не совпадать с твоими.
GZ>Я бы не сказал что он поддерживает функциональный стиль. Он поддерживает функциональные фичи. Для того чтобы поддерживать функциональный стиль, компилятор как минимум должен оптимизировать код написанный в данном стиле. Хотя бы корневую рекурсию (используемый стек то ограничен). А этого здесь нет.
Кстати, недавно с удивлением узнал, что оказывается поддержка хвостовой рекурсии встроена в CLR — команда tail ret, если не ошибаюсь.
Здравствуйте, Igor Trofimov, Вы писали:
iT>Кстати, недавно с удивлением узнал, что оказывается поддержка хвостовой рекурсии встроена в CLR — команда tail ret, если не ошибаюсь.
Появилась в 2.0 и дико тормозит. Меж тем обычный goto решает все проблемы на ура.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Курилка,
GZ>>>Если есть, можешь дать ссылку на описание мат. основы монад?
LCR>>Lomeo садист LCR>>Хотя может быть у тебя пойдёт лучше чем у меня. LCR>>На всякий случай прими во внимание ещё пункт 6 в этом списке
Ну, хоть что-то новое в нашем болоте... воинт ООП — это радикально ново!
Что касается вопроса о естественности изменяемого состояния, то отвечу просто — бывает по разному. Бывают ситуации которые хорошо лучше эмулируются изменяемым состоянием, бывает наоборот.
Приведу в пример учет. Учет в широком финансовом смысле этого слова.
Вот предположим нам надо учитывать сколько денег осталось в кубышке. Мы создаем объект "деньги", объект "кубышка", а так же сообщения "добавить денег в кубышку" и "изьять деньги из кубышки". Оба сообщения хранят ссылаются на деньги помещаемые или изымаемые из кубышки.
Здорово? Похоже — да. Удобно? Для того чтобы сказать сколько денег сейчас в кубышке — вполне!
Но всегда ли это здорово?
Что если нам вдруг захочется узнать какой оборот был за определенный период? Или, скажем, сколько денег было в кубышке на конкретное число?
А ничего. Ничего хорошего. Наша модель не рассчитана на это. Ведь она всего лишь эмулирует реальный мир.
А что же далеть, чтобы наша модель позволяла решать поставленные задачи?
А очень просто! Надо всего лишь запрерить менять объекты, а вместо этого складывать сообщения в единое хранилище, откуда их можно будет извлечь и проанализировать.
Чувствуете куда я клоню? Правильно... к базам данных — шутка.
Я клоню к тому, что не всегда с точки зрения задачи изменение состояния — это благо.
Например, для большинства вычислительных задач функциональный стиль предпочтителен. ООП же изумительно подходит для задач симуляции и манипуляции. Ну, право, не глупо ли выражать онко Виндовс в виде фукнции?!
В общем, пусть цветут все цветы, главное чтобы они хорошо пахли. ООП никак не противоречит ФП и оба этих подхода никак не противоречат процедурному. На против они изумиетельно совмещаются. Главное уметь понять где какой предпочесть.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
EC>Language Integrated Query (LINQ) is a framework that is rooted
EC>in the theoretical ideas of monads and monad comprehensions to
EC>allow seamless querying over objects, XML, and relational data.
это я наверно могу пояснить. list comprehension все знают? вот пример его применения для поиска троек пифагора:
при этом list comprehension — это фактически специальная запись для обычного кода, использующего монаду List:
triangles n = do x<-[1..n]
y<-[x..n]
z<-[y..n]
guard$ x^2+y^2==z^2
return (x,y,z)
т.е. как видите монада используется сначала для перебора значений в некотором источнике, а затем для отсеивания тех, которые нас не устраивают, при этом описание перебираемого набора и условий отбора коструируется последовательно, предложение за предложением. в linq, как я понимаю, используется что-то похожее, и его операции — это statement'ы монады, перебирающие источник данных или отсекающие ненужные значения. не знаю, правда, как group by в это вписан
VD>И что они тогда делают?
L>>Простой пример — монада списка.
VD>Тот же вопрос.
VD>Ответы про монады, как сами монады — аморфны и выскальзают из рук. Никогда не получишь прямого и однозначного ответа.
По поводу монады списка.
Смотри.
Вот определение монады List
instance Monad [] where
m >>= f = concatMap f m
return x = [x]
fail s = []
ConcatMap делает следующее — делается map(f) для указанного списка, и результат конкатенируется.
public class List : IMonad
// грубо говоря делаем map функции f на списокpublic IMonad.Bind(m, f)
{
ConcateMap(f, m)
}
// оборачиваем X любого типа в список. Теперь Х просто так не достать.
//Он спрятан внутри монады (или класса List)
//и доступ к нему возможен только через интерфейсы,
//поддерживаемые классом List. В нашем случае это только IMonadpublic IMonad.Return(x);
{
return new List(x);
}
// А здесь просто возвращаем пустой список.public IMonad.Fail(s)
{
return new List();
}
Вот собственно и все.
There is no spoon.
Еще пришла в голову ассоциация.
В качестве примера рекурсии часто используется вычисление факториала. Но без tail оптимизации оно значительно менее эффективно чем императивное решение в лоб. Однако это не значит что сама идея рекурсии ущербна. Да, если реализовывать фаткориал в лоб, ничего хорошего не получится. Но ведь рекурсию еще можно применить в куче разных мест. Точно так же и с монадами. Ввод вывод в Хаскеле мне самому не шибко нравится. Он мне непривычен. Но та же монада List весьма интересная штука.
Здравствуйте, Cyberax, Вы писали:
C>Функциональное программирование — это совершенно другой стиль. C>Ортональный ООП и противоположный императивному.
In programming three important perspectives are:
— Function oriented programming: The computing process is viewed as a sequence of applications of functions to an input, producing an output, that in its turn may be the input to another functions etc.
— Object oriented programming: The computing process is viewed (as described above) as the development of a system, consisting of objects (components), through sequences of changing states.
— Constraint oriented programming: The computing process is viewed as a deduction process, developing from an initial state, the process being restricted by sets of constraints and inputs from the environment, information about the states being deduced by an inferencing algorithm. Logic programming using first order predicate logic is currently the most important example (Prolog).
It seems obvious to the author that all these three perspectives should be supported within any new general programming language in the future. No perspective will "win" as some seem to believe.
BZ>>это и есть global state на уровне треда.
AVK>Только в случае, если сервис опубликован в корневом сервис-менеджере. А если не в корневом, то только в пределах его контекста. А дальше все уже зависит от конкретного приложения. Монады тут ничего не меняют, бо проблема логическая, а не технологическая.
монады — это (в данном случая) механизм неявной передачи параметра во все процедуры, вызываемые из данной. т.е. если мы написали, что во всех выхзовах внутри вот этого делать логгинг в один файл, а во всех вызовах внутри этого делать логгинг в другой, то так оно и будет работать
вообще, мне кажется, что вы с этими паттернами за деревььями не видите леса. как это не обзови и в какие объекты не заверни, это thread-local state, не больше и не меньше. монады, как их не обхови — в данном случае просто способ передать параметр во все нужные вызовы. thread-local state проблему на 100% не решает, параметры же — решают, и при наличии такого средства в языке все эти дополниьтельные параметры совершенно не усложняют структуру программы
LaPerouse wrote: > Повторяю — функциональное программирование является разновидностью > процедурного, нравится вам это или нет.
Да даже близко не является. Процедурное программирование — это
подмножество императивного стиля.
Функциональное программирование — это совершенно другой стиль.
Ортональный ООП и противоположный императивному.
VladD2 wrote: >> > Прости, ты в курсе, что в С и Паскале есть поддержка ФВП? > C>В классическом Паскале, по-моему, нет. > Значит на счет С ты согласен?
Ну да, С как и Perl может быть WOP-языком (Whatever Oriented Programming).
> C>Это не их основной стиль. Нет поддержки функциональных конструкций > C>непосредственно в языке. > Правильно. Теперь становится очевидно, что наличие ФВП само по себе ще > не дотсточно чтобы о языке можно было сказать, что он функциональный или > поддерживает функциональный стиль.
Естественно, это необходимое, но не достаточное условие.
Просто тут был тезис, что ФП — это подмножество процедурного
программирования. Я привел пример свойства, которым процедурное
программирование не обладает, но которое необходимо для ФП. Вот и все.
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
VD>>Прости, ты в курсе, что в С и Паскале есть поддержка ФВП?
LCR>Это указатели на функции что-ли?
Угу. Кстати если мне не изменяет мой склероз в каком-то Паскале (TP? BP ? )были типизированные указатели на функции.(Или это уже в делфи появилось... )
В общем Sort() с передачей метода принимающего 2 значения типа обжект и возвращающего -1,0,1 в зависимотси от результата сравнения имел место быть.
Здравствуйте, Cyberax, Вы писали:
C>ФП невозможен без какой-либо формы ФВП.
ФВП нет в Sisal. Не было их в Лиспе и в Эрланге, что не мешало им быть функциональными.
Здравствуйте, Cyberax, Вы писали:
C>Лямбды — это действительно просто сахар, хотя такой же необходимый для C>ФП, как и циклы for/while для ИП, которые являются сахаром над if/goto.
Вообщето, это именованная функция сахар для лямбды, а не наоборот. По крайней мере в Haskell именно так, если мне память не изменяет. Но это не принципиальная претензия — с остальным я, в принципе, согласен.
... << RSDN@Home 1.2.0 alpha rev. 655>>
'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
Здравствуйте, Klapaucius, Вы писали:
K>Вообщето, это именованная функция сахар для лямбды, а не наоборот. По крайней мере в Haskell именно так, если мне память не изменяет. Но это не принципиальная претензия — с остальным я, в принципе, согласен.
Хотя нет, не совсем. Главное это не ФВП, а функции, являющиеся FCO — тут есть нюанс — это не одно и то же.
... << RSDN@Home 1.2.0 alpha rev. 655>>
'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
Здравствуйте, Трурль, Вы писали:
C>>ФП невозможен без какой-либо формы ФВП. Т>ФВП нет в Sisal. Не было их в Лиспе и в Эрланге, что не мешало им быть функциональными.
Извиниття ! Куда это high order функции из ерланга проелись ?
Вот живой пример :
Fun3=fun(Fun1,Fun2)-> Fun1() + Fun2() end.
Это кусочек парсера скриптового языка. Делает из 2-х подвыражений лямбду, которая их складывает.
На входе — функции.
На выходе — тоже функция. Стало быть, high order functions из Erlang никто не утащил, воспользовавшись ночным мраком и плохой погодой...
Mirrorer,
LCR>>Это указатели на функции что-ли?
M>Угу. Кстати если мне не изменяет мой склероз в каком-то Паскале (TP? BP ? )были типизированные указатели на функции.(Или это уже в делфи появилось... ) M>В общем Sort() с передачей метода принимающего 2 значения типа обжект и возвращающего -1,0,1 в зависимотси от результата сравнения имел место быть.
Согласен, имел.
M>Согласно википедии этого достаточно M>
In mathematics and computer science, higher-order functions or functionals are functions which do at least one of the following:
M> * take one or more functions as an input
M> * output a function
Однако не слишком строгое определение, заметь. То есть это определение можно трактовать очень вольно. Как то что этим свойством обладают все функции (в математическом смысле), так и то, что этим свойством могут обладать некоторые функции.
Две большие разницы. Например, верни мне указатель на
1. функцию Medved(_, 22, _) получающуюся после частичного применения числа 22 к среднему аргументу функции Medved(x, y, z).
2. функцию f, которая является частной производной функции Medved(x, y, z) по второму аргументу y.
Короче, у нас путаница возникла из-за слияния двух альтернатив:
1. Если мы поставим тождество между указателями на функции и просто функцииями. Отсюда следует неравенство наличия ФВП и наличия функций как первоклассных объектов, всё так, как говорит Влад в этом сообщении
2. Если же функции и указатели на функции разделять, то указанное выше вики-определение подразумевает наличие функий как первоклассных объектов. Следовательно наличие ФВП равносильно наличию функций как первоклассных объектов.
Так что здесь флуктуации чисто терминологические: называть ли функцию, принимающую указатель на другую функцию, ФВП или нет.
Я предпочитаю второй вариант, но дискутировать на эту тему мне бы не хотелось бы по понятным причинам.
Mirrorer,
LCR>>Например, верни мне указатель на LCR>>1. функцию Medved(_, 22, _) получающуюся после частичного применения числа 22 к среднему аргументу функции Medved(x, y, z). M>Мммммм.. Тут какой интресный вопрос возникает.. Считать ли partial application необходимым условием для ФВП?
M>А если серьезно, то это вопрос наличия опять же partial application и\или лямбд. Хотя имея лямбды можно организовать partial application.. Получается что наличие лямбд достаточное условие для поддержки языком ФВП ?
Ну нужно ещё уметь передавать лямбды в качестве параметров и возвращать их. (Это равносильно требованию иметь лямбды как первоклассные значения).
Здравствуйте, Mirrorer, Вы писали: LCR>>Например, верни мне указатель на LCR>>1. функцию Medved(_, 22, _) получающуюся после частичного применения числа 22 к среднему аргументу функции Medved(x, y, z). M>Мммммм.. Тут какой интресный вопрос возникает.. Считать ли partial application необходимым условием для ФВП?
А что тогда ВП?
Вроде как это возможность
а) принять функцию как аргумент
б) вернуть функцию как результат
в) уметь возвращать разные функции как результат выполнения.
г) уметь возвращать ранее не существовавшие функции как результат выполнения
Для partial application требуется именно г). Если его нету, то какие-то у нас ФВП получаются убогие: не позволяют конструировать функции. В С++ ФВП можно эмулировать при помощи функторов, и то я не вполне уверен, что этого реально достаточно.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, LaPerouse, Вы писали:
LP>По этой ссылке — это что, шутка? Если нет, то это общество моральных уродов.
Шутка, затянувшаяся. Хотя, каждый воспринимает кащенитов по своему. Этот конкретный документ — пародия на масонские документы (уставы?).
LP>Очень жаль, но у вас сложилось неверное впечатление
Просто я бы сказал, что Вашим высказываниям в данной теме присущи черезмерный максимализм, псевдо-философия (?) (не поймите меня неправильно), углубленность а также не совсем адекватное понимание термина "функциональное программирование". Их просто сложно читать. Также рекомендую ознакомиться с определением из Википедии, и, для примера, форумом.
Здравствуйте, VladD2, Вы писали:
M>>Lisp (хоть он и не является ФЯ, как таковым) VD>Сколько раз я уже слышал это глубочайшее заблуждение. Откуда вы берете это ерись?
Из спецификаций.
VD>Лисп прородитель всех ФЯ. В нем концепции ФЯ были сормированы и опробированы. Все ФЯ клоны лиспа в некотором смысле.
Классический Лисп — да. Но в настоящее время он оброс. Поэтому сказать, что это ФЯ — нельзя, хотя в нем больше функционального, чем императивного.
Здравствуйте, konsoletyper, Вы писали:
K>>>Можно сказать больше. Прародителем является лямбда-исчисление. Лямбда исчисление — функциональные машинные коды. Лисп — функциональный ассеблер. ML — функциональный C. OCaml — функциональная Java.
АХ>>Nemerle?
K>Как ни парадоксально, его уместно "сравнить" с C++.
Ага, у меня те же мысли.
АХ>>Haskell?
K>Ну, наверное ADA.
Здравствуйте, VladD2, Вы писали:
VD>А чем тогда отличается концевая рекурсия? Она же тоже работает исключительно в рамках одного метода?
Ничего подобного. Префикс tail. применим к любому вызову.
VD>В Моно эта инструкция работает отлично. VD>Сдается мне все же, что это не более чем отговорка тех кто криво реализовал данную возможность.
Нет, в Моно просто неоптимизирован обычный вызов
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Cyberax, Вы писали: C>Если честно, мне не хочется вспоминать синтаксис указателей на функции C>из C, а то бы написал
Всё понятно. Ты заметил, что тебе пришлось поменять содержимое Reduce по сравнению с первым вариантом?
В принципе, задачу можно считать решенной, но в таком виде С немногим лучше ассемблера. Т.е. тебе пришлось изобрести другой язык в рамках С. Другой он потому, что не все С конструкции в нем верны. В частности, в f->func обязательно нужно передавать f, но компилятор за этим проследить не сможет.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, ironwit, Вы писали:
I>сложные у вас задачи. Нам для АСКУЭ этого хватает в общем то.
Это мои бывшие задачи ! Сейчас я работаю в другом месте, и занимаюсь совершенно другими вещами. Но ужасы приведения дат помню до сих пор. Хотя, и кроме этого проблем хватало...Тысячи кв. километров промышленных сетей, с приборами, датчиками, и телеуправлением. На таких задачах я впервые крупномасштабно использовал Ерланг, ибо он рожден для подобной распределенщины
Здравствуйте, VladD2, Вы писали:
VD>Пусть так. Один фиг для в доску императивного и к тому же объектно ориентированного языка все это не имеет смысла. В LINQ используются банальные лямбды и методы расширения
Не только. Есть еще expression tree. Но эта фича и к монадам и к функциональному программированию вобще имеет весьма отдаленное отношение.
VD>причем тут спрашивается монады?
Здравствуйте, AndrewVK, Вы писали:
L>>SelectMany == bind, имхо, остальные операторы тоже представляют собой монадические комбинаторы.
AVK>И при чем тут LINQ? SelectMany это просто статический метод в классе Sequence. То что он extension method, это просто синтаксический сахар. AVK>Вобщем, идея о том, что LINQ это монады на мой вкус кажется крайне странной.
В буквальном смысле (если брать за определение реализацию в Haskell) конечно нет, но идея оттуда.
Я не ожидал, что будут читать буквально.
Исходный смысл моего поста в том, что монады штука не безполезная и LINQ тому подтверждение.
Здравствуйте, AndrewVK, Вы писали:
AVK>И при чем тут LINQ? SelectMany это просто статический метод в классе Sequence. То что он extension method, это просто синтаксический сахар. AVK>Вобщем, идея о том, что LINQ это монады на мой вкус кажется крайне странной.
Ага. Чатая "этот" вспоминаешь знаменитые слова Гебельса — чем чудовищнее лож, тем больше шансов, что в нее поверят.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, BulatZiganshin, Вы писали:
BZ>>т.е. как видите монада используется сначала для перебора значений в некотором источнике, а затем для отсеивания тех, которые нас не устраивают, при этом описание перебираемого набора и условий отбора коструируется последовательно, предложение за предложением. в linq, как я понимаю, используется что-то похожее, и его операции — это statement'ы монады, перебирающие источник данных или отсекающие ненужные значения. не знаю, правда, как group by в это вписан
VD>Замечательно. Но причем тут монады? Это проблемы реализации императивных алгоритмов на Хаскеле. Таких проблем ни в одном ООЯ нет в помине, так как в них есть объекты с изменяемым состаянием.
Монада — это контейнерный тип данных, который представляет собой экземпляр класса Monad,
так же это экземпляр класса Functor, который декларирует наличие одной функции высшего порядка, преобразующей значения в контейнере в соответствии с некоторой функцией.
Как видишь довольно общая идея, применение которой можно найти не только в Haskell.
Механизмы LINQ (трансформация одной последовательности в другую) ложаться в её рамки,
а то, о чём ты говоришь не более чем частные случаи.
EC>>Т.е., по твоему, не в чистом ФЯ от них толку нет?
Q>Тольку мало. Они вносят оверхед, трудны для понимания и грязны с теоретической точки зрения (должны выполняться законы, которые не проверить автоматически). Из-за возможности создать неправильную монадуу компилятор не может провести оптимизацию, исходя из общих монадических законов.
в хаскеле они тожде не являются частью языка, и для них нет автооптимизаций, связанных с выполнением этих законов. какой удар!
EC>Монада — это контейнерный тип данных, который представляет собой экземпляр класса Monad,
EC>так же это экземпляр класса Functor, который декларирует наличие одной функции высшего порядка, преобразующей значения в контейнере в соответствии с некоторой функцией.
Это все попытки объяснить людям что такое монада в Хаскеле. Таких попыток море. И каждая из них исползует свои аналогии.
Фатк же остается фактом. Монада не имеет смысла в императивном языке. В C# есть объекты. У объектов есть состояние которое можно менять как угодно. Такое изменение будет всегда совершенно последовательным. Так что в ООП монада — это идиотизм.
EC>Как видишь довольно общая идея, применение которой можно найти не только в Haskell.
Эта "общая идея" была известна в математике. И Хаскель ее использует для прикрытия перехода в императивное вычисление. Да, в Хаскеле действительно нунжны некие объекты изменение которых происходит последовательно. Ведь обычне вычисления в Хаскеле не последовательныи не могут ничего изменить. Но в языке где и так можно мегять все что движется, а что не движется раскачивать и менять, это на фиг не упало.
EC>Механизмы LINQ (трансформация одной последовательности в другую) ложаться в её рамки, EC>а то, о чём ты говоришь не более чем частные случаи.
В концпцию монад ложится любое императивное вычисление. Это не странно. Или ты будешь утверждать, что чтение файла в C# — это тоже моды?
LINQ не более чем громкое название того что существовало сто лет до этого — вычислений с использованием фукнций высшего порядка и лямбд используемых для передачи конкретизирующих функций. Никакие монады для его обяснения не нужны.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
palm mute,
>> Вот мне любопытно, что такого плохого станется, если поднять >> императив на уровень языка и использовать его в ограниченном контексте?
PM>Я не понял, чем твое предложение отличается от уже имеющейся монады ST. PM>Не развернешь мысль?
Хочется внутри таких "преобразователей состояния" использовать обычное структурное программирование с обычными управляющими конструкциями.
Здравствуйте, VladD2, Вы писали:
VD>Фатк же остается фактом. Монада не имеет смысла в императивном языке. В C# есть объекты. У объектов есть состояние которое можно менять как угодно. Такое изменение будет всегда совершенно последовательным. Так что в ООП монада — это идиотизм.
А вот тут влезу я
В целом мысль которую я буду излагать где-то уже говорил lomeo, но что-то не могу найти сходу.
Монады имеют точно такой же смысл как любой интерфейс.
Точно такой же, как IEnumerable или IList. Только интерфейс называется IMonad.
Аналогия. Представь себе язык без массивов. Вообще. Только списки. И есть набор списков реализующих IList. Допустим List, Queue, Dictionary. А какой-то умник при помощи этого IList умудрился сэмулировать Array. То есть в языке как таковом массивов нет, но мы их эмулируем используя всем известный интерфейс.
Понятное дело что для языков, в которых массивы были отродясь Array реализованный через IList выглядит по меньшей мере извращением и мозго.. в общем brainfuck-ом. Но это не значит что сама идея интерфейса IList ущербна, и что классы List, Queue, Dictionary не нужны в языке поддерживающием массивы.
Монада это интерфейс. КАК его использовать — личное дело каждого. И какие классы будут реализовывать этот интерфес в целом неважно. Важно то, что они будут иметь унифицированный интерфейс.
AndrewVK wrote: > > Контекст еще есть. И не обязательно это TLS.
Каким образом этот контекст попадает в точку вызова сервиса? Я
пробежался по описанию Фаулера, но сути не уловил. Ну, есть синглтон с
хэш-таблицей именованных объектов-сервисов (их еще и кастить надо,
тьфу), дальше что? Кто и как обеспечивает деление на уровни и доставку
контекста, в двух словах?
, как легко PM>такие конструкции определить. Для применения в ограниченном контексте PM>вполне подходит. Гипотетические проблемы с лифтингом, которые мы PM>обсуждали ниже, возникнут, если этот ограниченный контекст раздуть, и в PM>этом случае действительно желательно рассмотреть вариант с FFI. Иметь 2 PM>яызка в одном — не слишком хорошая идея, IMHO.
Блин, ну неужели трудно понять, что 90% здоровых на голву людей бросят сам язык когда дойдут до этого самого лифтинга. Это все равно что заливать в перегретый автомабиль воду из кипящего чайника!
И все это ради того чтобы не признать правды — мир императивен и "чистоту" надо просто отделять от "императивной грязи".
Эта концепция проста для понимания. А все эти лифтинги, реалврлды, монады и т.п. — это булш который никогда не даск языка вроде Хаскеля стать действительно популярными.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, palm mute, Вы писали:
PM>Каким образом этот контекст попадает в точку вызова сервиса? Я PM>пробежался по описанию Фаулера, но сути не уловил. Ну, есть синглтон с PM>хэш-таблицей именованных объектов-сервисов (их еще и кастить надо, PM>тьфу), дальше что? Кто и как обеспечивает деление на уровни и доставку PM>контекста, в двух словах?
Блин, орлы, вы вообще там с со своим ФП офигели что ли? Человек думает в терминах ООЯ. И у него в подкорке лежит то что если он работает с потоками, то они поисываются классом. В этот класс можно запихнуть любое состояние и оно будет пренадлежать потоку. Оно будет всегда доступно. А считать это явной доступностью или нет уже дело вкуса.
Главное, что костыли вроде монад в ООЯ ненужны.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, palm mute, Вы писали:
PM>Ай-ай-ай, бедные-бедные 90% здоровых людей. PM>Злые языки говорят, уровень обсуждения на рсдн начал падать, это правда?
Правда. Стольк содержательные сообщения его сильно портят.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Люди принимают догмат "чистоты", но сразу же придумывают другой догамт позволяющий эту чистоту обойти. Казалось бы так все просто. В ФЯ любая функция при одном наборе аргументов обязана вернуть один определенный результат. Это помогает во многих случаях. Там распраллеливание, простота отладки, и еще много чего, но вот увы это не вяжется с реальным миром. В любом ООЯ мы просто создали бы объект в который положили бы ссылку на перменную или, как это предлагаешь ты, на хитрый объект сервис-локатор, но увы у нас догмы. Мы не может это сделать. Тогда мы придумываем хитрую чтоуку называем ее поумнее и вуаля обходим наши же ограничения.
по-твоему, паттерны проектирования появились потому, что в ООП такие вещи просто сделать?
сам представь, что проще — вызвать одну функцию на верхнем уровне (запустить эту монаду) или добалвять во _все_ объекты то или иное свойство?
Здравствуйте, BulatZiganshin, Вы писали:
VD>>Слова "query monad, как в HaskellDB, над которым, кстати, он работал" вообще каша какая-то. Какое отношение "query monad" из HaskellDB имеет к C#. И какое отношение между сравнением чего-то с чем-то из другого языка имеет к наличию этого в другом языке? И соттвественно оправданию лозунгов вроде "LINQ это монады для мейнстрима."?
BZ>собственно, LINQ, как и HaskellDB — интерфейс к БД. в HaskellDB для этого использована специальная монада, которая позволяет пошагово уточнить выполняемый запрос, т.е. ты можешь написать что-то вроде:
BZ>selectFrom "table" >>= groupBy "order" >>= ...
BZ>и >>= будет стратегией вычислений, формирующей из отдельных вызовов выполняемый оператор sql. в linq, вероятно, точно так же
Насколько я понял именно так и есть, т.е. это адаптация озвученной тобой идеи и решения для VB и C#.
Здравствуйте, BulatZiganshin, Вы писали:
BZ>собственно, LINQ, как и HaskellDB — интерфейс к БД. в HaskellDB для этого использована специальная монада, которая позволяет пошагово уточнить выполняемый запрос,
Здорово! То есть в Хаскеле для реализации функции Х используется монада. Ну, и причем тут C#? Почему в нем то должно использоваться то что в нем нет, и на фиг не упало?
В Хаскеле и для доступа к файлмам используется монада. И что?
Хотя конечно это вопрос не к тебе, а к тем странным личностям, что пытаются узреть монады в Шарпе.
BZ>и >>= будет стратегией вычислений, формирующей из отдельных вызовов выполняемый оператор sql. в linq, вероятно, точно так же
В linq используются ФВП. Там завели стандартные функции но с другими именами:
Select -> map
OrderBy -> Sort
Where -> Folter
и т.п. Далее сделали для этого дела спец-синтаксис, чтобы можно был писать похоже на SQL-запрос, т.е вместо:
xs.Where(x => x > 3).OrderBy(x).Select(x => new { x.a, x, b })
можно было писать:
from xs where x > 3 order by x select new { x.a, x, b }
и все. А некторые пытаются узреть в этом монады.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, BulatZiganshin, Вы писали:
BZ>далее. сделав в языке две ипостаси — чистые функции и процедуры, ты должен будешь продумать язык отдельно для каждой из них, продумать их правила взаимодействия и т.п.
Это не так. Все что нужно (по минимуму) чтобы превратить любй ФЯ в ИЯ = это добавить возможность объявления изменяемой переменной и оператор присвоения. А все императивные конструкции безпробем делаются из функциональных в сочетании с присониями переменных.
BZ>здесь же потери были бы ещё больше. и никакого выигрыша. фактически, сам pure язык позволяет сформулировать концепцию процедуры в нём, используя этот трюк с realworld.
Вот realworld это ханжеский булшит. По сути тот же Хаскель имеет оператор присвоения <- но в извращенно-завуалированной форме. И мы без проблем можем писать инмперативный код, но раком.
BZ> и тогда вместо того, чтобы формулировать правила для процедур отдельно, они просто выводятся из общих правил для любых pure функций, становятся их частным случаем. общее кол-во концепций в языке уменьшается, а это не может не радовать
Если бы такое "уменьшение" было бы благом, то в Хаскеле даже числа были бы перечислениями объявленными в каком-нить модуле. Все же есть вещи которые проще зашить в язык. И императивная составляющая одна из таких вещей.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Вот realworld это ханжеский булшит. По сути тот же Хаскель имеет оператор присвоения <- но в извращенно-завуалированной форме. И мы без проблем можем писать инмперативный код, но раком.
Как программист пишет код — хоть на голове, это его личное дело. А вот результат ничем не будет отличаться от императивного кода на другом языке. КАК это представлено внутри — без разницы. Поскольку realworld реально не используется — мы получим обычное последовательное (читай императивное) исполнение кода безо всяких realworld.
Что тебя смущает, не пойму? Выглядит код как императивный, компилируется и работает как императивный, что ещё надо то?
BZ>> и тогда вместо того, чтобы формулировать правила для процедур отдельно, они просто выводятся из общих правил для любых pure функций, становятся их частным случаем. общее кол-во концепций в языке уменьшается, а это не может не радовать
VD>Если бы такое "уменьшение" было бы благом, то в Хаскеле даже числа были бы перечислениями объявленными в каком-нить модуле.
Не придумывай. Дело не в том, что уменьшение не благо, а в том, что это просто невозможно. Во всём остальном числа (целые) ведут себя как обычные перечисления.
VD>Все же есть вещи которые проще зашить в язык. И императивная составляющая одна из таких вещей.
EC>В некоторых европейских ВУЗах его используют как первый язык программирования при обучении. EC>Я правда не настаиваю, что Haskell идеальный язык для этого.
а по-моему, как раз идеальный — чистая математика без всякиз побочных явлений. именно на нём надо изучать понятие алгоритма, учиться составлять их, а затем уже переходить к более никзоуровневым языкам
EC>>В некоторых европейских ВУЗах его используют как первый язык программирования при обучении. EC>>Я правда не настаиваю, что Haskell идеальный язык для этого.
BZ>а по-моему, как раз идеальный — чистая математика без всякиз побочных явлений. именно на нём надо изучать понятие алгоритма, учиться составлять их, а затем уже переходить к более никзоуровневым языкам
Я не настаиваю, но и не отрицаю, правда доказывать не стану — устал буквы писать
Здравствуйте, BulatZiganshin, Вы писали:
BZ>представьте себе сериализатор объекта. он рекурсивно вызывает сериализаторы подобъектов. локальности не получается
Что мен его представлять то? Я его сто раз писал. И ни разу с помощью монад... слава богу.
Объекты вообще не должны знать о сериализаторах. Они или должны содержать код сериализации в самих себе или сериализатор должен быть внешний (изучающий структуру объектов через рефлексию или АПИ компилятора).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
S>Вот мне, к примеру, жутко интересно, что общего у Linq и монад. Мое несовершенное понимаение монад сводится к чему-то вроде "способ управлять композицией функций". В Linq ничего похожего на управление способом композиции функций нет. S>Вот что такое Linq: S>1. Extension Methods (жизненно важны для того, чтобы запросы могли работать по любым коллекциям, в том числе и самым абстрактным)
S>Из этого списка сходство с возможностями монад имеет только п.4, и то это весьма отдаленное сходство. Если ты так хорошо понимаешь суть сходства Linq и монад, тебе не составит труда кратко обозначить, какие из перечисленных мной возможностей связывают между собой эти понятия. Не отвечая вопросом на вопрос и не ссылаясь на ссылки на цитаты. А?
как я понимаю, композиция этих extension methods в haskelдВи делалась как раз с помощтю монады. что давало возможность писать императвиный код внутри этого как бы sql-запроса. можежь сравнить это с List monad — она перечисляет все значения в списке и позволет тебе выполнить какие-то вычисления над ними, или отфильтровать их
Здравствуйте, Sinclair, Вы писали:
S>4. Анонимные типы. Аналогично анонимным делегатам, помогает избавиться от мусорного кода по декларированию временных структур только для того, чтобы передать данные от одного фрагмента запроса к другому. S>5. Спец.синтаксис для SQL-Like запросов. Совершеннейший сахар; ничего особенного не дает.
S>Из этого списка сходство с возможностями монад имеет только п.4, и то это весьма отдаленное сходство. Если ты так хорошо понимаешь суть сходства Linq и монад, тебе не составит труда кратко обозначить, какие из перечисленных мной возможностей связывают между собой эти понятия. Не отвечая вопросом на вопрос и не ссылаясь на ссылки на цитаты. А?
Тройка замечаний.
1. Все же не анонимные делегаты, а анонимные методы. Это так мелкая придирка. Их почему-то все путают.
2. Анонимные типы — это аналог (кастрированный) кортежей (tuple-ов) и к монадам он отношения не имеет.
3. Булщит зелепил не он, а ЕвилЧилд, а данный товарищь просто решил его поддержать.
По сути же соверешнно согласен. Ребата натрепались, а теперь духу не хватет признаться, что ошиблись.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>По сути же соверешнно согласен. Ребата натрепались, а теперь духу не хватет признаться, что ошиблись.
По сути у меня мнение польностью противоположное. Тебе показали, а у тебя духу не хватает признать, что ты ошибся. Вот и начинаешь говорить — где показали, да ещё раз покажите.
Здравствуйте, VladD2, Вы писали:
VD>Так. Извини, но мне надоело принимать в бесполезной словесной переплаке. Ты встал в ряд демагогов. Если будет сказть что-то интересное, то я с удовольствием выслушаю. А смотреть на словесную эквилибристику и контр-аргументацию в стиле "нет не белое, а белое" не не интересно.
Надоело — не принимай. Демагогией же пока занимаешься ты, не списывай, пожалуйста, свои достоинства на меня.
Заявить, что "белое — это когда белое, только не совсем белое", а потом удивляться, что ему возражают, ты умеешь.
VD>>>Из двух решений всегда надо выбрить более простой и понятное если коенчнь оно подходит L>>Нет. Из двух решений всегда надо выбирать подходящее
Ладно, поправлю фразу. БОЛЕЕ подходящее. Так пойдёт?
Заметь простота тут не указывается
VD>Адью.
Здравствуйте, VladD2, Вы писали:
GZ>>>А почему бы не через continuations? Можно доказать то же самое — но без термина монада. PM>>continuations выражаются через монады .
VD>ОК, господа трепачи. Вот вам C#. Монады вы на нем сотворите без проблем, это вы уже тут раз дващцать сказали. Тогда пользуясь истенностью вашего послендего утверждения "continuations выражаются через монады" и реализуйте, плиз, в C# continuations. Лично скажу вам огромное спасибо и поклонись до земли. Ну, а если кода не будет, то будем считать это силивом по полной порогрмме на чем и закончим эту дисскуссию.
Здравствуйте, Mirrorer, Вы писали:
VD>>Но менее фунционально. Ведь пример с исключениями останавливается на превой ошибке. M>Монадный вариант тоже вываливается на первой ошибке. Так что функцонал тот же.
Но есть же тот что не вываливается. И размер у него почти тот же.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
AndrewVK wrote: > M>Эх.. Да, жаль сообщения редактировать нельзя.. Подправил бы. Но в > целом не так уж важно. > Это хороший пример, почему на rsdn польтзователям нельзя редактировать > сообщения. Ну подправил бы ты. А письмо Влада осталось. И кто потом это > бы прочел, долго бы удивлялся о чем идет речь.
Поэтому надо хранить историю изменений и помечать к какой ревизии
относятся ответы.
Я бы не сказал что он поддерживает функциональный стиль. Он поддерживает функциональные фичи. Для того чтобы поддерживать функциональный стиль, компилятор как минимум должен оптимизировать код написанный в данном стиле. Хотя бы корневую рекурсию (используемый стек то ограничен). А этого здесь нет.
Здравствуйте, LaPerouse, Вы писали:
LP>Честно говоря, мне непонятны все эти попытки связать нововведения в языке с "поддержкой функционального программирования". Функциональное программирование как парадигма устарела еще в 70-ых годах вместе с процедурным программированием, подвидом которого оно является. Все эти лямды следует рассматривать лишь как синтаксический сахар (как и вывод типа). призванный сократить запись и освободить программиста от рутинных объявлений.
Ну да, конечно. Поразительный факт состоит только в том, что функциональное программирование начало развиваться только в конце 70-х. Именно тогда появились ML и первый функциональный диалект Lisp — Scheme. Если вы не понимаете фундаментальной разницы между императивным и функциональным подходом к написанию программ, лучше не позорьтесь, промолчите.
VladD2 wrote: > C> ФП от ИП является использование ФВП — Функций Высших Порядков. *ВСЁ* > Прости, ты в курсе, что в С и Паскале есть поддержка ФВП?
В классическом Паскале, по-моему, нет.
> Если, да, то ответь на вопрос: Почему никто не считает эти языки > функциональными?
Это не их основной стиль. Нет поддержки функциональных конструкций
непосредственно в языке.
Здравствуйте, Cyberax, Вы писали:
>> Прости, ты в курсе, что в С и Паскале есть поддержка ФВП? C>В классическом Паскале, по-моему, нет.
Значит на счет С ты согласен?
>> Если, да, то ответь на вопрос: Почему никто не считает эти языки >> функциональными? C>Это не их основной стиль. Нет поддержки функциональных конструкций C>непосредственно в языке.
Правильно. Теперь становится очевидно, что наличие ФВП само по себе ще не дотсточно чтобы о языке можно было сказать, что он функциональный или поддерживает функциональный стиль.
Вообще, причисление языка к ФЯ вопрос довольно спорный. Я бы ограничился утверждением, что язык может обладать тем или иным количеством возможностей пришедших из ФП и улучающих программирование в этом стиле.
С С/С++ этих возможностей явно недостаточно. В Хаскеле почто только они и есть. В ОКамл их более чем достаточно...
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2 wrote: > C>Ну да, С как и Perl может быть WOP-языком (Whatever Oriented Programming). > Не может. Мордой лица не вышел.
Может-может. Даже точный GC к нему прикручивается (см. GCC). Другое
дело, что ничего не делается просто.
> C>Просто тут был тезис, что ФП — это подмножество процедурного > C>программирования. Я привел пример свойства, которым процедурное > C>программирование не обладает, но которое необходимо для ФП. Вот и все. > Процедурному программированию по фигу есть ВФП или нет.
Собственно, я с этим не спорю — я это утверждаю. Может посмотришь на те
посты, на которые я отвечал.
Здравствуйте, Igor Trofimov, Вы писали: iT>Кстати, недавно с удивлением узнал, что оказывается поддержка хвостовой рекурсии встроена в CLR — команда tail ret, если не ошибаюсь.
Ее изобретали любители ФП. Реализация оказалась связана с проблемами с CAS: для работы CAS необходимо иметь доступ к неразрушенному стеку. В итоге, реализаторам пришлось эмулировать нормальный стек через технологическое отверстие, что оказалось медленнее, чем наивная реализация. Я не в курсе, существует ли решение для этой проблемы.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, GlebZ, Вы писали:
GZ>Я бы не сказал что он поддерживает функциональный стиль. Он поддерживает функциональные фичи.
+1. Собственно, несмотря на фразу самого автора про “language that supports a functional style of programming”,
из всех дальнейших оговорок про "There are currently no plans" и "are not entirely like" это неявно и вытекает.
GZ>Хотя бы корневую рекурсию (используемый стек то ограничен). А этого здесь нет.
Может "хвостовую" (tail)? Или я чего-то не знаю? Поддержка хвостовой рекурсии то есть (см. например здесь
Трурль wrote: > C>*ФП невозможен без какой-либо формы ФВП*. > ФВП нет в Sisal. Не было их в Лиспе и в Эрланге, что не мешало им быть > функциональными.
В Lisp'е нет ФВП??? А как же code is data is code и замыкания?
Про Sisal ничего не знаю, в Erlang'е ФВП есть (см. функции map или foreach).
Здравствуйте, Трурль, Вы писали:
Т>Здравствуйте, Cyberax, Вы писали:
C>>ФП невозможен без какой-либо формы ФВП. Т>ФВП нет в Sisal. Не было их в Лиспе и в Эрланге, что не мешало им быть функциональными.
Лиспа не знаю, но в Scheme точно есть
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Cyberax, Вы писали:
C>>Ну да, С как и Perl может быть WOP-языком (Whatever Oriented Programming).
VD>Не может. Мордой лица не вышел.
Здравствуйте, gandalfgrey, Вы писали:
Т>>ФВП нет в Sisal. Не было их в Лиспе и в Эрланге, что не мешало им быть функциональными. G>Извиниття ! Куда это high order функции из ерланга проелись ?
Кажется, у некоторых проблемы с восприятием грамматической категории времени глагола.
Естественным был бы вопрос: "откуда они взялись?".
gandalfgrey,
C>>>ФП невозможен без какой-либо формы ФВП. Т>>ФВП нет в Sisal. Не было их в Лиспе и в Эрланге, что не мешало им быть функциональными. G>Извиниття ! Куда это high order функции из ерланга проелись ? G>На входе — функции. G>На выходе — тоже функция. Стало быть, high order functions из Erlang никто не утащил, воспользовавшись ночным мраком и плохой погодой...
Всё совершенно верно, но лямбды в Эрланге появились не сразу. В OTP R5 и раньше они представлялись просто туплами. Кстати это и ответ на вопрос, почему gen_server:start_link принимают имя модуля, а не список функций-хэндлеров. Казалось бы самое непосредственное и напрашивающееся решение. Исторически так сложилось.
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>То есть это определение можно трактовать очень вольно. Как то что этим свойством обладают все функции (в математическом смысле), так и то, что этим свойством могут обладать некоторые функции.
+1
LCR>Например, верни мне указатель на LCR>1. функцию Medved(_, 22, _) получающуюся после частичного применения числа 22 к среднему аргументу функции Medved(x, y, z).
Мммммм.. Тут какой интресный вопрос возникает.. Считать ли partial application необходимым условием для ФВП?
LCR>2. функцию f, которая является частной производной функции Medved(x, y, z) по второму аргументу y.
Хотел бы я увидеть частную производную от Medved("preved","mishko","kosalapiy")
А если серьезно, то это вопрос наличия опять же partial application и\или лямбд. Хотя имея лямбды можно организовать partial application.. Получается что наличие лямбд достаточное условие для поддержки языком ФВП ?
LCR>Так что здесь флуктуации чисто терминологические: называть ли функцию, принимающую указатель на другую функцию, ФВП или нет.
+1 Но обычно в таком случае ломается больше всего копий. Как-то Объектный язык vs Объектно-ориентированный Ну или в новой интерпретации Функциональный или Функционально-ориентированный.
LCR> но дискутировать на эту тему мне бы не хотелось бы по понятным причинам.
+1. На вкус и цвет товарищи разные.
... << RSDN@Home 1.2.0 Pink Floyd — Don't Leave Me Now >>
Здравствуйте, Трурль, Вы писали:
Т> Кажется, у некоторых проблемы с восприятием грамматической категории времени глагола. Т>Естественным был бы вопрос: "откуда они взялись?".
Я не понимаю, что такое время, и признаю это открыто. Для меня это совершенно абстрактное понятие, никак не соотносящееся ни с реалиями жизни, ни с физическими феноменами...
Впрочем, я подразумевал именно массированную пропажу ФВП из различных языков и реализаций, поскольку очевидно, что у большинства из них в зародышево-личиночной стадии развития их не было. Ни у ерланга, ни у МЛя... Не знаю, как было дело с лиспом.
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
M>> Получается что наличие лямбд достаточное условие для поддержки языком ФВП ?
LCR>Ну нужно ещё уметь передавать лямбды в качестве параметров и возвращать их. (Это равносильно требованию иметь лямбды как первоклассные значения).
После некоторого размышления +1(Почему-то не смог сразу представить как это — иметь лямбды и не иметь возможности их возвращать). В следующий раз буду более подробно уточнять, что я имею ввиду.
... << RSDN@Home 1.2.0 Queen — I Want To Break Free >>
Насколько оно валидно —
Если есть ссылки на более авторитетные источники чем Wikipedia — Welcome!
S>Вроде как это возможность S>г) уметь возвращать ранее не существовавшие функции как результат выполнения S>Для partial application требуется именно г). Если его нету, то какие-то у нас ФВП получаются убогие: не позволяют конструировать функции.
Если ФВП = а И б И в И г , то таки да.
А если ФВП = а ИЛИ б ИЛИ в ИЛИ г, то вопрос остается открытым.
Здравствуйте, Mirrorer, Вы писали:
M>А можно тыксзть озвучить разницу понятным языком? А то я что-то до сих пор разницы не прочувствовал
Ну... Как здесь уже говорили в Pascal или в C можно с помощью ссылок на функцию организовать higher-order function, или в C# с помощью делегатов. Но функции первоклассными объектами в этих языках все равно не являются. Или я ошибаюсь?
... << RSDN@Home 1.2.0 alpha rev. 655>>
'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
Здравствуйте, Mirrorer, Вы писали:
M>Но это в том случае если принять, что указатель на функцию == функции.
M>Но опять же в таком случае в ассемблере ФВП тоже имеются... в M>общем. Но хотелось бы разобраться.
Реализовать можно всё, особенно если делать допущения. Но... то что можно реализовать — это хорошо, для языка. А "напрямую" оперировать понятиями — это уже другое. С теми же функциями... собственно мы в C можем их только вызывать, и на этом возможности заканчиваются. Речь ведь об этом?
Здравствуйте, VladGalkin, Вы писали:
VG>Здравствуйте, LaPerouse, Вы писали:
LP>>[...skipped]
VG>А Вы не кащенит ли случаем? А то Ваш ответ практически по "Кащенезису" построен.
По этой ссылке — это что, шутка? Если нет, то это общество моральных уродов. Очень жаль, но у вас сложилось неверное впечатление
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Здравствуйте, LaPerouse, Вы писали:
LP>Все-таки основным критерием функционального подхода является то, о чем я говорил выше – отношение к хранению состояния.
Ты забыл прставить ИМХО.
LP>Вот он, постамент, на котором зиждется вся теория и практика функционального программирования, тот самый “пятый элемент”, придающий особый колорит этому стилю.
А эти сопливые сантименты как к делу относятся?
LP>Стоит только разрешить изменение переменных в любом “функциональном языке” и внешние ссылки на эти переменные (которое не нужно даже специальным образом вводить), и этот язык неуловимо для глаз превратится в стандартный процедурный язык.
Именно так лисп в виде CL перестал быть "чистым" ФЯ. Но "стандартным" я бы его не назвал
LP>Все остальное – синтаксические конструкции, помогающие объявлять вложенные конструкции функций, встроенные в сам язык возможности для обработки списков и т п — все это для дураков,...
"От такого и слышу!" Это новый метод доказательства?
LP>...чтобы дать им почувствовать всю “революционность” и крутизну “новейшего” подхода.
"Откуда дровишки?" Это я про "новейший" подход? С какого забора ты читал этот маркетологический бред?
LP>Да! Я утверждаю, что за роскошной вывеской прячется тухлятина, которой уже как минимум 50 лет.
Про возраст — прав. Про оценку качества — "сам дурак"
LP>И готов это доказать любому, пусть и придется пожертвовать частью личного времени на восполнение пробелов в чужом образовании.
Что именно из этого крутого замеса полуправды, полулжи, стенаний девственницы и бреда маркетологов ты собираешься доказывать?
LaPerouse wrote: > C>Функциональное программирование — это совершенно другой стиль. > C>Ортональный ООП и противоположный императивному. > Видите ли, те языки, о которых вы говорите (C++, Pascal) в представлении > многих являются классическими процедурными языками, что нет ничего > недопустимого в усилении этого термина, которое более предпочтительно по > сравнению с введением нового термина – “функциональный язык”.
Это РАЗНЫЕ термины.
> Исходя из > того, что сказано мной выше, едва ли справедливо выделять из процедурных > группу функциональных языков, тут, скорее, нужно говорить о > “функциональном подходе” и о языках, наиболее эффективно поддерживающих > этот подход.
Так я могу сказать, что ВСЕ стили программирования — это процедурный стиль.
На Паскале и чистом С можно писать объектно-ориентировано (см. GTK,
GNOME). Делает ли это язык C ООП-языком? Нет, не делает.
На чистом С можно писать с использованием точного grabage collector'а
(см. внутреннее устройство GCC). Делает ли это язык С языком с GC? Нет,
не делает.
На чистом С я могу писать для многопроцессорных машин. Но это не делает
язык С языком с встроным параллелизмом.
И так далее.
> Все-таки основным критерием функционального подхода является то, о чем я > говорил выше – отношение к хранению состояния.
Да ничего оно не является. Куча функциональных языков имеют неявное
глобальное состояние. Даже в Haskell'е оно есть в виде монад.
Размещу ответ на том же уровне, т к обращаюсь ко всем ответившим на последний вопрос.
На основании ваших ответов можно заключить, что никто из вас не отвергает приближения ФЯ->Проц. язык. Таким образом, загвоздка заключается только в употребляемых терминах. Под функциональным языком вы имеете ввиду процедурный язык с явными ограничениями ввиде запрещений внешних ссылок, изменяемых переменных и т п. Прекрасно. В таком случае и доказывать-то мне ничего не остается — разве что недопустимость использования устаревшей парадигмы.в сегодняшних задачах. Но я хочу говорить не об этом.
Мне часто приходится слышать слова о том, что императивное программирование далека от человеческого мышления, т к якобы предполагает указание явной последовательности действий. Однако это совершенно не соответсвует действительности. Если императивность ограничить с помощью грамотно спроектированного ООП-дизайна (т е по сути применить декларативный подход), можно получить модель, удивительно отражающую реальность, которую она представляет. Давайте рассмотрим конкретный пример. Функциональщики, например, любят говорить возникающих в императивных программах сайд-эффектах. Рассмотрим двух людей и один единственный стул. Каждый из них на нем время от времени сидит. Данная ситуация очень ээфективно представляется с помощью соответсвующих классов (стул, человек) и объектах (два человека, стул). Рассмотрим среду, относительно которой сущществование этих объектов является гобальным (частный случай — эти объекты объявлены глобальными). В один момент один из людей проявляет желание сесть на этот стул. В этот момент другой опрокидывает его. Сайд-эффект? Безусловно (мы предполагаем, что это опрокидывание произошло случайно, непреднамеренно). Тогда, если первый человек не приоверит состояние стула, то грохнется (то соответсвует началу неправильного течения программы.) Но на то и даны глаза человеку, чтобы смотреть, на что садишься. На то и даны программисту исключения, чтобы в нужный момент осуществлять проверки и вызывать exception. Я хочу сказать таким образом, что САЙД-ЭЭФЕКТЫ, ВОЗНИКАЮЩИЕ ПРИ ОБЪЕКТНО-ОРИЕНТИРОВАННОМ ПРОГРАММИРОВАНИИ, ГЛУБОКО ЕСТЕСТВЕННЫ, ОНИ ХАРАКТЕРНЫ ДЛЯ ТОЙ РЕАЛЬНОСТИ, КОТОРУЮ ОПИСЫВАЕТ ОБЪЕКТНАЯ МОДЕЛЬ. Функциональный подход, такой "человечный и естественный", в данном случае совершенно не будет отражать естественного поведения вещей. При моделировании данной ситуации на ФЯ мы не сможем иметь глобальные объекты ввиде стула и людей. Мало того, что при изменении состояния объекта объект как бы пересоздается (что совершенно неестественно), так еще повторение данной ошибки невозможно из-за того, что первый человек уже ОЖИДАЕТ стул, находящийся в перевернутом состоянии.
Мне хотелось бы пна ваши комментарии по этому поводу.
Социализм — это власть трудящихся и централизованная плановая экономика.
Здравствуйте, LaPerouse, Вы писали:
LP>Размещу ответ на том же уровне, т к обращаюсь ко всем ответившим на последний вопрос.
LP> Рассмотрим двух людей и один единственный стул. Каждый из них на нем время от времени сидит. Данная ситуация очень ээфективно представляется с помощью соответсвующих классов (стул, человек) и объектах (два человека, стул). Рассмотрим среду, относительно которой сущществование этих объектов является гобальным (частный случай — эти объекты объявлены глобальными). В один момент один из людей проявляет желание сесть на этот стул. В этот момент другой опрокидывает его. Сайд-эффект? Безусловно (мы предполагаем, что это опрокидывание произошло случайно, непреднамеренно). Тогда, если первый человек не приоверит состояние стула, то грохнется (то соответсвует началу неправильного течения программы.) Но на то и даны глаза человеку, чтобы смотреть, на что садишься. На то и даны программисту исключения, чтобы в нужный момент осуществлять проверки и вызывать exception. Я хочу сказать таким образом, что САЙД-ЭЭФЕКТЫ, ВОЗНИКАЮЩИЕ ПРИ ОБЪЕКТНО-ОРИЕНТИРОВАННОМ ПРОГРАММИРОВАНИИ, ГЛУБОКО ЕСТЕСТВЕННЫ, ОНИ ХАРАКТЕРНЫ ДЛЯ ТОЙ РЕАЛЬНОСТИ, КОТОРУЮ ОПИСЫВАЕТ ОБЪЕКТНАЯ МОДЕЛЬ. Функциональный подход, такой "человечный и естественный", в данном случае совершенно не будет отражать естественного поведения вещей. При моделировании данной ситуации на ФЯ мы не сможем иметь глобальные объекты ввиде стула и людей. Мало того, что при изменении состояния объекта объект как бы пересоздается (что совершенно неестественно), так еще повторение данной ошибки невозможно из-за того, что первый человек уже ОЖИДАЕТ стул, находящийся в перевернутом состоянии.
LP>Мне хотелось бы пна ваши комментарии по этому поводу.
Вы привели какой-то совершенно левый пример, который можно легко решить даже на самом заскорузлом процедурном языке. Вводим функцию сесть над парой структур — человек и стул, вот и все дела.
Функциональное программирование не против состояний, но эти состояния не глобальны, а локальны. В этом главное отличие ФП от ПП и оно совершенно все меняет. Что вам дает state centric подход? То, что вы можете сидеть за клавиатурой и медитировать на тему того, что стул упал? Не хватает соображения работать не с глобальным состоянием, которое меняется рывками в строгой последовательности, а во многих местах помаленьку? Поэтому в рамка функционального подхода ваш вопрос бессмысленен, функционального программиста не интересует лежит стул или нет, его интересует, что с этим стулом будет происходить дальше. Ваша же картина полностью статична, поэтому можно просто объявить переменную человек два раза и опрокинутый стул один раз, этого достаточно.
Q>Ну да, конечно. Поразительный факт состоит только в том, что функциональное программирование начало развиваться только в конце 70-х. Именно тогда появились ML и первый функциональный диалект Lisp — Scheme. Если вы не понимаете фундаментальной разницы между императивным и функциональным подходом к написанию программ, лучше не позорьтесь, промолчите.
Императивное программирование начало развиваться в 30-х годах 20-го века. Только тогда появилась мшина Тьюринга — императивный аналог лямбда-исчисления.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Здравствуйте, LaPerouse, Вы писали:
LP>Мне часто приходится слышать слова о том, что императивное программирование далека от человеческого мышления, т к якобы предполагает указание явной последовательности действий.
Да нет, на самом деле обывателю понятнее имератинвый стиль. А вот математики (которые, кстати, благодаря своей способности формализовать что угодно решают задачи, просто фантастические для обывателя) привыкли думать статично и метафизически. Им должен быть ближе функциональный стиль. Но здесь я не побоюсь высказать своё ИМХО: чтобы решать сложные задачи, прораммист должен быть немножко математиком.
LP>Однако это совершенно не соответсвует действительности. Если императивность ограничить с помощью грамотно спроектированного ООП-дизайна (т е по сути применить декларативный подход), можно получить модель, удивительно отражающую реальность, которую она представляет.
Открвываем любой вузвоский учебник по математике или физике и читаем. Что же мы там можем увидеть? А то, что в начале вводятся несколько фундаментальных законов. В принципе, они очень красиво описывают модель реальности. Но из этого на практике не следует ровным счётом ничего. Потому оставшиеся 90% книжки описывают частные приближения. Так же и с программированием. В пределах какой-то модели мы всё можем описать красиво. Но вот когда дело доходит до практики, общие методы отдыхают. Приходится выбирать наиболее рациональное частное решение. И будет оно в рамках имеративного, функционального или ещё какого-либо ещё программирования, должно зависеть исключительно от решаемой задачи, а не от личных предпочтений программиста или от догматики.
Здравствуйте, Sinclair, Вы писали:
S>А что тогда ВП? S>Вроде как это возможность S>а) принять функцию как аргумент S>б) вернуть функцию как результат
...
Не "уметь", а фукнция принимающая или возрващающая другую функцию. Все! Если язык это позволяет, то он поддерживает ФВП. Так что С их однозначно поддерживает.
А вот большинство те кто использует этот термин путают его с трактованием функций как первоклассных значений. Что конечно включает поддержку ФВП, но не ограничивается ею.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Klapaucius, Вы писали:
K>Ну... Как здесь уже говорили в Pascal или в C можно с помощью ссылок на функцию организовать higher-order function, или в C# с помощью делегатов. Но функции первоклассными объектами в этих языках все равно не являются. Или я ошибаюсь?
В C# 2.0 практически функция являектся первокласным объктом. Картину малось портят проблемы с делегатами, но по сути тех же характеристик добиться можно. Хотя конечно в языках исходно поддерживающих ФП все выглядит значительно чище.
От того лично я склоняюсь к определению: ФЯ это язык целенаправленно поддерживающий программирование в функциональном стиле и имеющий широкий спктр встроенны фич упрощающих программирование в этом стиле.
C# балансирует на грани. Он уже имеет довольно важные фукнции, но пока недотягивает до действительно фунциональных языков.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Klapaucius, Вы писали:
K>Здравствуйте, Mirrorer, Вы писали:
M>>Но это в том случае если принять, что указатель на функцию == функции.
K>Так в том и дело, что указатель на функцию != функции.
Это детали реализации. И вообще что значит функци?
Это ее код? Тогда ни один компилируемый язык не может поддерживать ФВП. Хотя... Как тогда расценивать эксперементы Рихтера по передачи кода функций из процесса в процесс?
Это некий идентификатор однозначно определяющий функцию? Тогд почему им не может быть указатель на фукнцию?
K>Собственно, в той же Википедии и об этом написано здесь
Читаем:
The modern, natively compiled programming languages support functions defined statically at compile time. Most of them, e.g. C and Pascal, additionally support function pointers, which can be stored in data structures and passed as arguments to other functions. Nevertheless, they are not considered to support first class functions, since, in general, functions cannot be created dynamically during the execution of a program.
То есть рассуждения с ФВП переходят на ФСО. Другими словами начинается подмена понятий.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Опять-т аки мой ответ адресуется обеим участникам, ответившим на мой вопрос, хотя и расположен вынужденно в неподобающем месте (что за скверный движок форума).
Ничего нового вы мне не сказали. Как совершенно правильно заметил Quintanar, в случае с ФП мы имеем дело с множеством локальных состояний вместо вполне определенных глобальных. В этом-то и состоит неестественность ФП, оторванность от реальности, именно поэтому на ФЯ тяжело реализуются соврмененные промышленные системы. Но вы ошибаетесь, считая, что я совсем свожу роль ФЯ на нет. Мне кажется, данная группа языков может быть оптимальной для решения очень узкой группы задач преимущественно вычислительного характера. В частности, ФЯ были бы очень к месту в CAD-системах в качестве внутренних языков. На них, быть может, легче решать небольшие, локальные задачи. Но для крупной разработки промышленного уровня применение данного подхода оптимальным назвать нельзя.
Мое мнение, возможно, незначительно изменится после ознакомления хотя бы с одним из этих языков (до этого у меня не было реального опыта применения).
Социализм — это власть трудящихся и централизованная плановая экономика.
В С и Паскале есть ФВП, но они не являются First-Class Values.
Точно в дырочку!
Кстати, такая путанница возникает даже у искушенных дядь. Мы тут как раз сейчас публикуем переводную статью по Хаскелю и в ней точно такая же путанница.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, fddima, Вы писали:
F> Реализовать можно всё, особенно если делать допущения. Но... то что можно реализовать — это хорошо, для языка. А "напрямую" оперировать понятиями — это уже другое. С теми же функциями... собственно мы в C можем их только вызывать, и на этом возможности заканчиваются. Речь ведь об этом?
Кто тебе сказал, что мы их можем только вызвать? Погляди, например, ради хохмы описание функции qsort() из стандартной библиотеки.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2 wrote: > F> Реализовать можно всё, особенно если делать допущения. Но... то что > можно реализовать — это хорошо, для языка. А "напрямую" оперировать > понятиями — это уже другое. С теми же функциями... собственно мы в C > можем их только вызывать, и на этом возможности заканчиваются. Речь ведь > об этом? > > Кто тебе сказал, что мы их можем только вызвать? Погляди, например, ради > хохмы описание функции qsort() из стандартной библиотеки.
Это ещё не хохма.. Хохма — в VCL. Там где-то надо передать более-менее
делегат (procedure of object) в качестве callback в функцию WinAPI,
которая, увы, принимает только указатель на функцию, без лишнего
указателя. Ну так там просто-таки создаётся новая функция — результат
вырожденного частичного применения (остаётся процедура без
аргументов)... Но как это сделано... На стеке выделяется место и туда
пишутся машинные коды и в некотором месте в immediate data записывается
тот самый указатель, которого не хватает для счастья. Так как обычно
Executable Stack допустим, всё работает.
Здравствуйте, Sinclair, Вы писали:
S>Ее изобретали любители ФП. Реализация оказалась связана с проблемами с CAS: для работы CAS необходимо иметь доступ к неразрушенному стеку. В итоге, реализаторам пришлось эмулировать нормальный стек через технологическое отверстие, что оказалось медленнее, чем наивная реализация. Я не в курсе, существует ли решение для этой проблемы.
Хм. А goto почему проблем с CAS не вызывает?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, raskin, Вы писали:
R>Это ещё не хохма.. Хохма — в VCL. Там где-то надо передать более-менее R>делегат (procedure of object) в качестве callback в функцию WinAPI, R>которая, увы, принимает только указатель на функцию, без лишнего R>указателя. Ну так там просто-таки создаётся новая функция — результат R>вырожденного частичного применения (остаётся процедура без R>аргументов)... Но как это сделано... На стеке выделяется место и туда R>пишутся машинные коды и в некотором месте в immediate data записывается R>тот самый указатель, которого не хватает для счастья. Так как обычно R>Executable Stack допустим, всё работает.
Это как раз к языку отношения не имет. Это как раз эмуляция.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
The modern, natively compiled programming languages support functions defined statically at compile time. Most of them, e.g. C and Pascal, additionally support function pointers, which can be stored in data structures and passed as arguments to other functions.
+1
Я ошибся — указатели конечно не являются функциями, но структуры данных могут содержать указатели, и можно построить структуру (скажем такая {указатель на функцию, список типов для параметров, тип для возвращаемого значения}), которую можно назвать "функцией". ФВП будут те процедуры, которые принимают/возвращают такие структуры.
В вики написано нормально (за исключением момента, что не очень понятно, что там понимается под "функцией").
Здравствуйте, VladD2, Вы писали:
VD>Все остальное – синтаксические конструкции, помогающие объявлять интерфейсы, встроенные в сам язык возможности итирации по коллекция и т п — все это для дураков
Всё же интерфейсы придуманы скорее не для дураков, а для поддержки КОП.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, raskin, Вы писали:
R>Но как это сделано... На стеке выделяется место и туда R>пишутся машинные коды и в некотором месте в immediate data записывается R>тот самый указатель, которого не хватает для счастья.
А вот в стандатном паскале можно просто передать локальную функцию.
Здравствуйте, gandalfgrey, Вы писали:
G>Я не понимаю, что такое время,
Судя по реакции на мое сообщение, ты в этом не одинок G>и признаю это открыто.
А вот это уже редкость.
Здравствуйте, LaPerouse, Вы писали:
LP>На основании ваших ответов можно заключить, что никто из вас не отвергает приближения ФЯ->Проц. язык. Таким образом, загвоздка заключается только в употребляемых терминах. Под функциональным языком вы имеете ввиду процедурный язык с явными ограничениями ввиде запрещений внешних ссылок, изменяемых переменных и т п. Прекрасно. В таком случае и доказывать-то мне ничего не остается — разве что недопустимость использования устаревшей парадигмы.в сегодняшних задачах. Но я хочу говорить не об этом.
Функциональная и императивная парадигмы появились приблизительно в одно время. Императивная раньше была воплощена в виде машины, которую уже можно было использовать.
Здравствуйте, Трурль, Вы писали:
G>>Я не понимаю, что такое время, Т>Судя по реакции на мое сообщение, ты в этом не одинок
Конечно, не одинок ! Нас — таких -много..."Имя нам — легион" (с)
Более того, существуют некоторые бытовые заморочки со временем, которые не понятны НИКОМУ из моих знакомых.
Пример :
Есть прибор, собирающий значения какого-то параметра раз в час. Как известно, 2 раза в год у нас происходит перевод времени.
То-есть один день в году имеет 23 часа и после 1 часу ночи наступает сразу 3 час. Другой день имеет 25 часов, и после 2 часов ночи наступает снова 2 часа ночи.
Как быть, куда бежать ? Никакого внятного, корректного и более-менее универсального способа обработать такую ситуацию пока не придумано.
Так что — такова се ля ва ! 8)
Трурль wrote: > R>Но как это сделано... На стеке выделяется место и туда > R>пишутся машинные коды и в некотором месте в immediate data записывается > R>тот самый указатель, которого не хватает для счастья. > > А вот в стандатном паскале можно просто передать локальную функцию.
А разве там можно её передать так, чтобы она ссылалась на переменные
функции на шаг выше?
VladD2 wrote: > R>Это ещё не хохма.. Хохма — в VCL. Там где-то надо передать более-менее > R>делегат (procedure of object) в качестве callback в функцию WinAPI, > R>которая, увы, принимает только указатель на функцию, без лишнего > R>указателя. Ну так там просто-таки создаётся новая функция — результат > R>вырожденного частичного применения (остаётся процедура без > R>аргументов)... Но как это сделано... На стеке выделяется место и туда > R>пишутся машинные коды и в некотором месте в immediate data записывается > R>тот самый указатель, которого не хватает для счастья. Так как обычно > R>Executable Stack допустим, всё работает. > > Это как раз к языку отношения не имет. Это как раз эмуляция.
К языку имеет отношение наличие делегатов. Которое в принципе позволяет
написать даже функцию, возвращающую сумму двух функций. А хохма связана,
действительно, не с языком, а с его взаимодействием с внешним миром,
когда даже такие зачатки приходится эмулировать.
M>>За возможность написать map(Fun, List) я бы продал Страуструпа с Виртом в рабство. Обоих
LCR>За эту фразу я бы поставил три балла! Если бы форум был КУ...
Я конечно понимаю, что это возможно и в С++ (а может и в Паскале), но вот такой ценой? Нее. Не надо Я лучше все в скрипты вынесу
LP>В частности, ФЯ были бы очень к месту в CAD-системах в качестве внутренних языков. На них, быть может, легче решать небольшие, локальные задачи. Но для крупной разработки промышленного уровня применение данного подхода оптимальным назвать нельзя.
Я бы все же ознакомился с вопросом, прежде, чем такое заявлять.
Haskell Lisp (хоть он и не является ФЯ, как таковым)
Ну и так далее. Часто бывает так, что об использовании таких языков открыто не заявляется, потому что использование таких языков является конкурентным преимуществом.
LP>Мое мнение, возможно, незначительно изменится после ознакомления хотя бы с одним из этих языков (до этого у меня не было реального опыта применения).
Здравствуйте, VladD2, Вы писали: VD>Хм. А goto почему проблем с CAS не вызывает?
Потому, что он работает только в пределах текущего метода. И стек сохраняется неизменным.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
K>Ну... Как здесь уже говорили в Pascal или в C можно с помощью ссылок на функцию организовать higher-order function,
А можно продемонстрировать мне, как это будет работать на С или Pascal? Элементарную функцию, которая делает из любой двухаргументной функции одноаргументную, связывая второй параметр?
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Sinclair wrote: > K>Ну... Как здесь уже говорили в Pascal или в C можно с помощью ссылок > на функцию организовать higher-order function, > А можно продемонстрировать мне, как это будет работать на С или Pascal? > Элементарную функцию, которая делает из любой двухаргументной функции > одноаргументную, связывая второй параметр?
Вспомни bind_1st/bind_2nd из STL и представь ее на С. Только вот
выглядеть будет еще более жутко.
Cyberax,
>> K>Ну... Как здесь уже говорили в Pascal или в C можно с помощью ссылок >> на функцию организовать higher-order function, >> А можно продемонстрировать мне, как это будет работать на С или Pascal? >> Элементарную функцию, которая делает из любой двухаргументной функции >> одноаргументную, связывая второй параметр? C>Вспомни bind_1st/bind_2nd из STL и представь ее на С. Только вот C>выглядеть будет еще более жутко.
Здравствуйте, Cyberax, Вы писали: C>Вспомни bind_1st/bind_2nd из STL и представь ее на С.
Не могу. Потому как stl вроде бы использует функторы и шаблоны, а в С ни того ни другого нету.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Sinclair wrote: > C>Вспомни bind_1st/bind_2nd из STL и представь ее на С. > Не могу. Потому как stl вроде бы использует функторы и шаблоны, а в С ни > того ни другого нету.
Функторы — элементарно:
struct Functor
{
int (*func)(int a, int b);
};
int add(int a, int b)
{
return a+b;
}
Functor * new_add_functor()
{
Functor *f=(Functor*)malloc(sizeof(Functor));
f->func=&add;
return f;
}
int reduce(List *lst, Functor *f)
{
int res=0;
while(lst!=null)
{
res=f->func(lst->data,res);
lst=lst->next;
}
return res;
}
//Суть понятна?
Точно так же делаем bind_1st/bind_2nd. Скорее всего потеряем возможность
generic-программирования, но может с помощью макросов можно будет
сделать что-то подобное.
Я такое где-то даже видел, но сейчас не вспомню где именно.
Здравствуйте, raskin, Вы писали:
R>А разве там можно её передать так, чтобы она ссылалась на переменные R>функции на шаг выше?
Вообще, можно.
procedure forall(l:IntList; procedure f(var i:integer));
begin
while l<>nil do begin f(l.head); l:=l.tail end;
end;
procedure foo;
var
a : Integer;
l:IntList;
procedure AddA (var i:integer);
begin
i:=i+a;
end;
begin
...
forall(l, AddA);
end;
Но заставить винапи поддерживать это,конечно, нельзя.
Трурль wrote: > R>А разве там можно её передать так, чтобы она ссылалась на переменные > R>функции на шаг выше? > > Вообще, можно. > > procedure forall(l:IntList; procedure f(var i:integer)); > begin > while l<>nil do begin f(l.head); l:=l.tail end; > end; > > procedure foo; > var > a : Integer; > l:IntList; > procedure AddA (var i:integer); > begin > i:=i+a; > end; > begin > ... > forall(l, AddA); > end;
Это не то, что я хотел, я имел в виду передать как возвращаемое
значение. Это я и сам умею. Передача WinAPI являлась выдачей значения
вовне дерева вызовов с корнем в носителе локальной функции, что именно
принимало функцию — не так важно/
Здравствуйте, Cyberax, Вы писали:
C>Sinclair wrote: >> C>Вспомни bind_1st/bind_2nd из STL и представь ее на С. >> Не могу. Потому как stl вроде бы использует функторы и шаблоны, а в С ни >> того ни другого нету. C>Функторы — элементарно: C>//Суть понятна?
Неа. Непонятна. Покажи мне какой-нибудь другой функтор, который можно передать в Reduce.
C>Точно так же делаем bind_1st/bind_2nd.
Пока не понимаю, как именно C>Скорее всего потеряем возможность generic-программирования, но может с помощью макросов можно будет сделать что-то подобное.
Пока что всё, что мы сделали — это усложненную передачу двухаргументной функции.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
G>Как быть, куда бежать ? Никакого внятного, корректного и более-менее универсального способа обработать такую ситуацию пока не придумано. G>Так что — такова се ля ва ! 8)
в 1 ситуации в данных дырка
во второй ситуации данные больше чем средние два раза, так как считаются два раза.
в итоге в среднем за год выходим на ноль погрешность.
Здравствуйте, Sinclair, Вы писали:
S>Потому, что он работает только в пределах текущего метода. И стек сохраняется неизменным.
А чем тогда отличается концевая рекурсия? Она же тоже работает исключительно в рамках одного метода? Не, можно конечно попробовать реализовать межметодную концевую рекурсию без инлайнинга, но это же отдельная задача. Ведь даже не решая ее сделать тупой переход в начало метода с изменением параметров вместо вызова — не проблема.
В Моно эта инструкция работает отлично.
Сдается мне все же, что это не более чем отговорка тех кто криво реализовал данную возможность.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
IT>>Всё же интерфейсы придуманы скорее не для дураков, а для поддержки КОП.
VD>Такое ощущание что фичи ФП придуманы для дурагой. Вообще — Сэр — странно видить у вас плохое чувство юмора.
Да я просто хотел уточнить.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
gandalfgrey wrote:
> Есть прибор, собирающий значения какого-то параметра раз в час. Как > известно, 2 раза в год у нас происходит перевод времени. > То-есть один день в году имеет 23 часа и после 1 часу ночи наступает > сразу 3 час. Другой день имеет 25 часов, и после 2 часов ночи наступает > снова 2 часа ночи. > Как быть, куда бежать ? Никакого внятного, корректного и более-менее > универсального способа обработать такую ситуацию пока не придумано.
А UTC для чего? Он не подвержен переводу времени, разница получается при отображении инфы о времени в некоторой
timezone. Проблема может быть лишь максимум при составлении отчётов за периоды с границами попадающими на дату перевода
стрелок.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
gandalfgrey wrote:
> Есть прибор, собирающий значения какого-то параметра раз в час. Как > известно, 2 раза в год у нас происходит перевод времени. > То-есть один день в году имеет 23 часа и после 1 часу ночи наступает > сразу 3 час. Другой день имеет 25 часов, и после 2 часов ночи наступает > снова 2 часа ночи. > Как быть, куда бежать ? Никакого внятного, корректного и более-менее > универсального способа обработать такую ситуацию пока не придумано.
А UTC для чего? Он не подвержен переводу времени, разница получается при отображении инфы о времени в некоторой
timezone. Проблема может быть лишь максимум при составлении отчётов за периоды с границами попадающими на дату перевода
стрелок.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, raskin, Вы писали:
R>Есть там цикл (loop). Многофункциональный, даже слишком.
Тады можно писать императивные программы. Ничто этому не мешает. Соответвенно — полное императивное программирование он поддерживает.
Здравствуйте, LaPerouse, Вы писали:
LP>Все-таки основным критерием функционального подхода является то, о чем я говорил выше – отношение к хранению состояния. Вот он, постамент, на котором зиждется вся теория и практика функционального программирования, тот самый “пятый элемент”, придающий особый колорит этому стилю. Стоит только разрешить изменение переменных в любом “функциональном языке” и внешние ссылки на эти переменные (которое не нужно даже специальным образом вводить), и этот язык неуловимо для глаз превратится в стандартный процедурный язык. Все остальное – синтаксические конструкции, помогающие объявлять вложенные конструкции функций, встроенные в сам язык возможности для обработки списков и т п — все это для дураков, чтобы дать им почувствовать всю “революционность” и крутизну “новейшего” подхода. Да! Я утверждаю, что за роскошной вывеской прячется тухлятина, которой уже как минимум 50 лет. И готов это доказать любому, пусть и придется пожертвовать частью личного времени на восполнение пробелов в чужом образовании.
Попробуй пописать на любом нефункциональном языке не пользуясь циклами и goto. (коих там нету).
Здравствуйте, GlebZ, Вы писали:
FR>>Это не ересь, это правда лисп настолько же функциональный насколько и императивный. GZ>Там есть оператор goto или цикл?
Здравствуйте, LaPerouse, Вы писали:
LP>Честно говоря, мне непонятны все эти попытки связать нововведения в языке с "поддержкой функционального программирования". Функциональное программирование как парадигма устарела еще в 70-ых годах вместе с процедурным программированием, подвидом которого оно является. Все эти лямды следует рассматривать лишь как синтаксический сахар (как и вывод типа). призванный сократить запись и освободить программиста от рутинных объявлений.
Здесь не Вы, случаем, изысканно беседу ведете? Стиль изложения похож, а вот лозунги местами разнятся.
Здравствуйте, FR, Вы писали:
FR>Это не ересь, это правда лисп настолько же функциональный насколько и императивный.
Это даже не ерись, это просто заблуждение. По таким рассуждениям функциональным может быть только Хаскель.
FR>Это не мешает ему одновременно быть и императивным.
Не путай "чстый фукциональный язык" и просто "фукциональный язык".
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, konsoletyper, Вы писали:
K>Здравствуйте, VladD2, Вы писали:
VD>>Лисп прородитель всех ФЯ. В нем концепции ФЯ были сормированы и опробированы. Все ФЯ клоны лиспа в некотором смысле.
K>Можно сказать больше. Прародителем является лямбда-исчисление. Лямбда исчисление — функциональные машинные коды. Лисп — функциональный ассеблер. ML — функциональный C. OCaml — функциональная Java.
Здравствуйте, Sinclair, Вы писали:
K>>Ну... Как здесь уже говорили в Pascal или в C можно с помощью ссылок на функцию организовать higher-order function, S>А можно продемонстрировать мне, как это будет работать на С или Pascal? Элементарную функцию, которая делает из любой двухаргументной функции одноаргументную, связывая второй параметр?
Это не имеет отношения к ФВП. ФВП просто принимает или возвращает фукнцию. Конструирование фукций — это уже более широкая задача.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Sinclair, Вы писали:
S>Неа. Непонятна. Покажи мне какой-нибудь другой функтор, который можно передать в Reduce.
На самом деле манипуляцией с указателями и динамическим распределением памяти можно сэмулировать все что угодно. Только это не будет уже возможностью языка и будет выглядеть жудко.
Вот только речь шла о ФВП, а чтобы функция была ФВП нет нужды иметь в языке возможность конструирования функций.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
FR>>Это не мешает ему одновременно быть и императивным.
VD>Не путай "чстый фукциональный язык" и просто "фукциональный язык".
Я и не путаю, лисп одинаково хорошо подерживает обе парадигмы.
Здравствуйте, Андрей Хропов, Вы писали:
K>>Как ни парадоксально, его уместно "сравнить" с C++. АХ>Ага, у меня те же мысли.
Его можно сравнивать с С++ только с точки зрения практики применения. Во всех остальных отношениях языки сранвать не размуно. Ведь Немерле имеет значительно более высокий уровень. И вообще, это гибрид со всеми вытекающими. По этому сравнивать можно толко отдельные фичи. У Лиспа похожи макросы. У ОКамла паттерн-матчино...
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, VladD2, Вы писали:
FR>>>Это не мешает ему одновременно быть и императивным.
VD>>Не путай "чстый фукциональный язык" и просто "фукциональный язык".
FR>Я и не путаю, лисп одинаково хорошо подерживает обе парадигмы.
ОКамл, Немерле, и тучи других языков "одинаково хорошо подерживает обе парадигмы", но от этого они не перестают быть функциональными. ФЯ — это языко поддерживающий ФП. Точка! Никаких дополнительных условий или оговорок нет. Вот C# не ФЯ потому как пока плохо поддерживает ФП, но процесс идет и в один прекрасный день он может стать вполне себе ФЯ. Да, гибридным. Но функциональным от все же будет. Так же как тот же ОКамл.
Лисп исходно был ФЯ и в виду жизненных потребностей обзавелся многими императивными возможностями. Ничего страшного в этом нет. Это не делает язык сразу другим.
Вообще для поддержки императивного программирования нужна только одна возможность — изменяемые переменные. Так вот оные есть в любом языке. Даже в приславутом Хаскеле. Так что или нам надо признать, что ни один язык не является ФЯ, так как не обладает полной чистаткой (не является сферокоником), или нам надо признать, что для того чтобы быть ФЯ достаточно просто хорошо поддерживать этот стиль программирования.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
FR>>Я и не путаю, лисп одинаково хорошо подерживает обе парадигмы.
VD>ОКамл, Немерле, и тучи других языков "одинаково хорошо подерживает обе парадигмы", но от этого они не перестают быть функциональными. ФЯ — это языко поддерживающий ФП. Точка! Никаких дополнительных условий или оговорок нет. Вот C# не ФЯ потому как пока плохо поддерживает ФП, но процесс идет и в один прекрасный день он может стать вполне себе ФЯ. Да, гибридным. Но функциональным от все же будет. Так же как тот же ОКамл.
И?
Я вообще-то тоже самое говорю
VD>Лисп исходно был ФЯ и в виду жизненных потребностей обзавелся многими императивными возможностями. Ничего страшного в этом нет. Это не делает язык сразу другим.
Лисп насколько я понимаю исходно был "языком обработки списков" и сразу подерживал и императивщину тоже.
VD>Вообще для поддержки императивного программирования нужна только одна возможность — изменяемые переменные. Так вот оные есть в любом языке. Даже в приславутом Хаскеле. Так что или нам надо признать, что ни один язык не является ФЯ, так как не обладает полной чистаткой (не является сферокоником), или нам надо признать, что для того чтобы быть ФЯ достаточно просто хорошо поддерживать этот стиль программирования.
Почему не один, шаблоны C++ и D вполне ФЯ
Так же и 99% Хаскеля
А серъезно не понятно о чем мы спорим? Наверно по привычке уже
Здравствуйте, VladD2, Вы писали:
K>>>Как ни парадоксально, его уместно "сравнить" с C++. АХ>>Ага, у меня те же мысли.
VD>Его можно сравнивать с С++ только с точки зрения практики применения.
И не только. Nemerle — это язык, воплотивший в себе симбиоз мэйнстрима и каких-то прогрессивных идей.
VD> Во всех остальных отношениях языки сранвать не размуно. Ведь Немерле имеет значительно более высокий уровень. И вообще, это гибрид со всеми вытекающими. По этому сравнивать можно толко отдельные фичи. У Лиспа похожи макросы. У ОКамла паттерн-матчино...
А какие есть общие фичи у ML и C? Вот лично я сравнивал не по фичам, а по общей позиции в функциональном и в императивном программировании.
Здравствуйте, Андрей Хропов, Вы писали:
АХ>>>Haskell?
K>>Ну, наверное ADA. АХ>
Та же самая история. Вроде очень красивый, строгий, сбалансированный язык, но массового распространения не получил. Однако умело воплотил некоторые актуальные идеи и в чём-то повлиял на развитие других языков.
Здравствуйте, GlebZ, Вы писали:
FR>>Это не ересь, это правда лисп настолько же функциональный насколько и императивный. GZ>Там есть оператор goto или цикл?
А что это меняет?
goto вообще ничего не поределяет кроме наличия неструктурных операторов.
Наличие цикла всего лишь следствие поддержки императивного программирования. Основным признаком его наличия является возможнось изменять переменные. Даже если в зыке нет циклов или goto, наличие такой возможности позволяет на нем писать императивно.
Но самое смешное, что возможность писат императивно ни коем образом не влияет на то может считатья язык функциональным или нет. Большинство функциональных языков поддрживают императивное программирование. Даже самые что ни на есть чистые языки вроде Хаскеля имеют возможности писать вполне императивный код. Без этого вообще невозможно использовать ЯП на практике. Ведь мир компьюетров в принципе императивен. Вывод на экран, в файл, взаимодействие с пользователем — это 100% имератив.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Без этого вообще невозможно использовать ЯП на практике. Ведь мир компьюетров в принципе императивен. Вывод на экран, в файл, взаимодействие с пользователем — это 100% имератив.
Ну, в принципе можно разработать аппаратную систему, поддерживающую чистое функциональное программрование. Пусть в ней есть n ячеек памяти. Тогда любая программа (пусть элемнтарным языком для такой системы будет "очищенный" Scheme) должна возвращать спосок из n stream-ов. Соответсвенно, сама система с определённым (очень малым) интервалом обращается к этому списку. Только построить такую систему — геморрой. Ещё больший геморрой — для неё прогать. Ну и конечно же тормоза...
Здравствуйте, konsoletyper, Вы писали:
K>Ну, в принципе можно разработать аппаратную систему, поддерживающую чистое функциональное программрование.
Только гипотетически. В конце концов такая система будет замкнутой сама в себе, а стало быть снова не будет иметь прикладного смысла.
K>Пусть в ней есть n ячеек памяти. Тогда любая программа (пусть элемнтарным языком для такой системы будет "очищенный" Scheme) должна возвращать спосок из n stream-ов. Соответсвенно, сама система с определённым (очень малым) интервалом обращается к этому списку. Только построить такую систему — геморрой. Ещё больший геморрой — для неё прогать. Ну и конечно же тормоза...
"Тормоза" — это конечно предубеждение. Другое дело, что не ясны пути реализации и пути взаимодействия с миром (императивныйм по сути своей).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
K>>Пусть в ней есть n ячеек памяти. Тогда любая программа (пусть элемнтарным языком для такой системы будет "очищенный" Scheme) должна возвращать спосок из n stream-ов. Соответсвенно, сама система с определённым (очень малым) интервалом обращается к этому списку. Только построить такую систему — геморрой. Ещё больший геморрой — для неё прогать. Ну и конечно же тормоза...
VD>"Тормоза" — это конечно предубеждение. Другое дело, что не ясны пути реализации и пути взаимодействия с миром (императивныйм по сути своей).
Ну, например, устройство вывода — монитор. Каждый пиксель — это stream из кортежей по три элемента. Функциональный "дисплей" периодически запрашивает следующие элементы из каждого такого stream'а и меняет соответствующим образом изображение. Устройства ввода — такой же stream. Если программа хочет читать что-то (например, с функциональной клавиатуры), она просто посдледовательно забирает элементы из этого stream-а. Другой вопрос, что такие вещи нафиг никому не нужны. Просто я хотел провести чёткую границу между принципиальной невозможностью и практической нецелесообразностью.
Кстати, мир тоже можно описывать не как императивный. В принципе, можно мир представить как функцию по времени. Этот подход такой же спорный, как и императивный. Пока физики не докопались до сути, непонятно, императивен мир или функционален. Но это всё не важно, главное применять тот или иной подход тогда, когда это целесообразно.
K>Ну, например, устройство вывода — монитор. Каждый пиксель — это stream из кортежей по три элемента. Функциональный "дисплей" периодически запрашивает следующие элементы из каждого такого stream'а и меняет соответствующим образом изображение.
Не, батенька. У дислея есть физические пиксели. Их изменение есть императив. Это действие которое обязано в определенной очередности и приводить. А чисто-функционал — это выражение. Например f(x) = x * x. Оно действие не подразумевает. Просто утверждение. Даже f(2) = 2 * 2 = 4 тоже только утверждение. А чтобы посчитать сколько будет 2 на 2 нужен некий императив. Вот в современных компьютерах таким императивом является логика АЛУ. У АЛУ есть до мозка костей императивные регистры в которые можно заложить поеранды, выполнить команду и снять резульат. Потому он и может что-то делать, в отличии от математики являющейся чистым знанием.
K> Устройства ввода — такой же stream. Если программа хочет читать что-то (например, с функциональной клавиатуры), она просто посдледовательно забирает элементы из этого stream-а. Другой вопрос, что такие вещи нафиг никому не нужны. Просто я хотел провести чёткую границу между принципиальной невозможностью и практической нецелесообразностью.
Ага. Вот фанаты чистой функциональности и изобретают шизу вроде фукнций на входе которых один мир, а на выходе другой. А по жизни это всего лишь выверты чтобы не видить основной проблемы — императивности мира.
K>Кстати, мир тоже можно описывать не как императивный. В принципе, можно мир представить как функцию по времени. Этот подход такой же спорный, как и императивный. Пока физики не докопались до сути, непонятно, императивен мир или функционален. Но это всё не важно, главное применять тот или иной подход тогда, когда это целесообразно.
Даже если сделать такое предположение, то у нас есть одна загвоздка. Любой компьюетер часть мира, а функциональная система должна быть замкнутой.
В общем, я расцениваю попытки обосновать разные монады и другие трюки как попытку подставить в уравнение недостающую констануту. Уравнение конечно может и сойтись, но вот чуство обмана все равно остается.
А куда как проще принять простой факт, что императив — это данность. И не надо с ней бороться. Часть сисетмы вполне себе может быть функциональной, а часть императивной. Одно другому не мешеет. Если хочется выделить императивный код, то достаточно его просто пометить. Тогда заумные обоснования будут на фиг не нужны, а язык будет пригоден для реального применения.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Это не имеет отношения к ФВП. ФВП просто принимает или возвращает фукнцию. Конструирование фукций — это уже более широкая задача.
Я понимаю, просто мне интуитивно казалось, что ФВП должны с этой функцией еще и что-то сделать .
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, VladD2, Вы писали:
K>>Ну, например, устройство вывода — монитор. Каждый пиксель — это stream из кортежей по три элемента. Функциональный "дисплей" периодически запрашивает следующие элементы из каждого такого stream'а и меняет соответствующим образом изображение.
VD>Не, батенька. У дислея есть физические пиксели. Их изменение есть императив. Это действие которое обязано в определенной очередности и приводить. А чисто-функционал — это выражение. Например f(x) = x * x. Оно действие не подразумевает. Просто утверждение.
Пусть у нас есть функция f(x, y, t), а функциональный дисплей сделан на основе ЭЛТ. Тогда дисплей во время хода луча просто вызывает эту функцию с различными (x, y), но с постоянной t. На следующем кадре (пусть это происходит через 0.01 сек) монитор прибавляет к t 0.01 и повторяет всю операцию уже с другим t.
В принципе, такое возможно. Практически очень тяжело.
VD>Даже f(2) = 2 * 2 = 4 тоже только утверждение. А чтобы посчитать сколько будет 2 на 2 нужен некий императив. Вот в современных компьютерах таким императивом является логика АЛУ. У АЛУ есть до мозка костей императивные регистры в которые можно заложить поеранды, выполнить команду и снять резульат. Потому он и может что-то делать, в отличии от математики являющейся чистым знанием.
Мы же говорим сейчас про софт. Можно построить железо, которое будет императивным по принципу работы, но функциональным с точки зрения программиста.
VD>Ага. Вот фанаты чистой функциональности и изобретают шизу вроде фукнций на входе которых один мир, а на выходе другой. А по жизни это всего лишь выверты чтобы не видить основной проблемы — императивности мира.
Ну, им виднее, зачем нужны такие выверты. Я вот просто люблю поиграться с гипотезами. Порой сам от своих гипотез в ужас прихожу...
K>>Кстати, мир тоже можно описывать не как императивный. В принципе, можно мир представить как функцию по времени. Этот подход такой же спорный, как и императивный. Пока физики не докопались до сути, непонятно, императивен мир или функционален. Но это всё не важно, главное применять тот или иной подход тогда, когда это целесообразно.
VD>Даже если сделать такое предположение, то у нас есть одна загвоздка. Любой компьюетер часть мира, а функциональная система должна быть замкнутой.
Можно рассмотреть часть мира. Всё равно современой науке точно неизвестно, что такое вселенная. Можно строить только частные модели для различных задач.
VD>В общем, я расцениваю попытки обосновать разные монады и другие трюки как попытку подставить в уравнение недостающую констануту. Уравнение конечно может и сойтись, но вот чуство обмана все равно остается.
+1
Возможно, это как-то продвинет теорию, не знаю. Но на практике нужны не обоснования а удобные и надёжные методы.
VD>А куда как проще принять простой факт, что императив — это данность. И не надо с ней бороться. Часть сисетмы вполне себе может быть функциональной, а часть императивной. Одно другому не мешеет. Если хочется выделить императивный код, то достаточно его просто пометить. Тогда заумные обоснования будут на фиг не нужны, а язык будет пригоден для реального применения.
Вот именно, что в любой задаче можно усмотреть императивную и функциональную части. И при этом ни в коем случае нельзя полагаться на то, что какая-либо из частей имеет преимущество над другой. Нужно для конкретной задачи решить, насколько она функциональна и насколько — императивна, независимо от личных взглядов и убеждений. Иногда, полагаю, может пригодиться чистая функциональность (но лично я с такими задачами не встречался).
В реальности все сложнее, чем на самом деле (с) I>в 1 ситуации в данных дырка
Дырку еще можно заполнить, хотя бы предыдущим часом...
I>во второй ситуации данные больше чем средние два раза, так как считаются два раза.
Интересны данные ИМЕННО за этот час. Если в 2 часа первый раз значение было низкое, а второй раз — аварийное, то какое из них использовать ? Усреднять нелбзя, а то получится средняя температура по больнице
I>в итоге в среднем за год выходим на ноль погрешность.
Если бы ! Дело даже не в погрешности, а в пропущенных аварийных / нештатных ситуациях. Все нилейно, поэтому такие простые вещи, как усреднение, не прокатывают
Пример : электромоторчик на 10 мегаватт. если он превысит среднюю мощность ( около 6 МВТ ), то срок его службы сократится на доли процента, что очень ощутимо по деньгам. А если мы будем сглаживать, то мы об этом рискуем не узнать и остаться в самый нужный момент с дохлым оборудованием.
Здравствуйте, ., Вы писали:
.>А UTC для чего? Он не подвержен переводу времени, разница получается при отображении инфы о времени в некоторой .>timezone. Проблема может быть лишь максимум при составлении отчётов за периоды с границами попадающими на дату перевода .>стрелок.
Все просто ! Все предприятия работают либо с московским, либо с локальным временем. И данные они хотят видеть именно в этом времени. А при конвертации из Гринвича оная проблема возникнет по новой.
gandalfgrey wrote:
> .>А UTC для чего? Он не подвержен переводу времени, разница получается > при отображении инфы о времени в некоторой > .>timezone. Проблема может быть лишь максимум при составлении отчётов за > периоды с границами попадающими на дату перевода > .>стрелок. > Все просто ! Все предприятия работают либо с московским, либо с > локальным временем. И данные они хотят видеть именно в этом времени. А > при конвертации из Гринвича оная проблема возникнет по новой.
Пофиг как работают предприятия. Программы и железо должны работать с UTC, а при отображении использовать установленную
timezone. Системный таймер во всех писюках работает именно так, и ни у кого с этим проблем не возникает.
Почему тот некий прибор должен выпендриваться московским временем?
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ., Вы писали:
.>Пофиг как работают предприятия. Программы и железо должны работать с UTC, а при отображении использовать установленную .>timezone. Системный таймер во всех писюках работает именно так, и ни у кого с этим проблем не возникает. .>Почему тот некий прибор должен выпендриваться московским временем?
Таковы производственные требования, однако. Изменить положение вещей — вне компетенции местного начальства.
ВСЕ сертифицированные для учета приборы используют локальное, в крайнем случае — московское время.
Здравствуйте, gandalfgrey, Вы писали:
G>Здравствуйте, ironwit, Вы писали:
G>В реальности все сложнее, чем на самом деле (с) I>>в 1 ситуации в данных дырка G>Дырку еще можно заполнить, хотя бы предыдущим часом...
сложные у вас задачи. Нам для АСКУЭ этого хватает в общем то.
gandalfgrey wrote:
> .>Пофиг как работают предприятия. Программы и железо должны работать с > UTC, а при отображении использовать установленную > .>timezone. Системный таймер во всех писюках работает именно так, и ни у > кого с этим проблем не возникает. > .>Почему тот некий прибор должен выпендриваться московским временем? > Таковы производственные требования, однако. Изменить положение вещей — > вне компетенции местного начальства. > ВСЕ сертифицированные для учета приборы используют локальное, в крайнем > случае — московское время.
Ну это уже оффтопик. Это проблема не софта/железа, а начальства. Проблема не компьютерная, а политическая. Если есть
желание, можешь попробовать поубеждать нужных людей.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ., Вы писали:
.>Ну это уже оффтопик. Это проблема не софта/железа, а начальства. Проблема не компьютерная, а политическая. Если есть .>желание, можешь попробовать поубеждать нужных людей.
Это проблема понимания, что такое время, и зачем оно бывает. Началось, как я помню, с замечания Трурля на эту тему, а я всего лишь живописал оную проблему.
Проблем с софтом и железом вообще не бывает. Все проблемы рождаются либо в голове, либо от недостатка таковой. 8)))))
Здравствуйте, Cyberax, Вы писали:
C>Да ничего оно не является. Куча функциональных языков имеют неявное C>глобальное состояние. Даже в Haskell'е оно есть в виде монад.
Глобального нет, есть локальное.
Хотя, конечно, хаками типа unsafePerformIO можно сделать и глобальное состояние:
ref = unsafePerformIO (newIORef 0)
readRef = readIORef ref >>= print
writeRef k = writeIORef ref k
Здравствуйте, konsoletyper, Вы писали:
K>Пусть у нас есть функция f(x, y, t), а функциональный дисплей сделан на основе ЭЛТ. Тогда дисплей во время хода луча просто вызывает эту функцию с различными (x, y), но с постоянной t. На следующем кадре (пусть это происходит через 0.01 сек) монитор прибавляет к t 0.01 и повторяет всю операцию уже с другим t.
В следствии того, что функция должна выдавать одинаковый результат для динаковых значений аргументов, ты получишь заранее определенный вывод на дисплей. Какой в этом смысл?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Sinclair, Вы писали:
S>Нет, в Моно просто неоптимизирован обычный вызов
Это попытка выдать желаемое за правду. А правда в том, что в моно эта инструкция дает резкий выигрыш на концевой рекурсии. В Немерле, напиример, для моно не используют собственные оптимизации, а для дотнета используют (концевую рекурсию заменяют на goto).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
S>>Нет, в Моно просто неоптимизирован обычный вызов
VD>Это попытка выдать желаемое за правду. А правда в том, что в моно эта инструкция дает резкий выигрыш на концевой рекурсии. В Немерле, напиример, для моно не используют собственные оптимизации, а для дотнета используют (концевую рекурсию заменяют на goto).
Здравствуйте, EvilChild, Вы писали:
VD>>Ага. Вот фанаты чистой функциональности и изобретают шизу вроде фукнций на входе которых один мир, а на выходе другой. А по жизни это всего лишь выверты чтобы не видить основной проблемы — императивности мира.
EC>Ты уверен, что то, что ты их не понимаешь делает их шизой?
Я уверен в том, что я понимаю, что и зачем они делают. От того и даю оценку.
EC>Я вот не понимаю, но так не думаю.
Какая разница что ты думаешь, если сам признаешь, что не понимаешь о чем говоришь?
EC>Интересно, с выходом LINQ твоё мнение изменится на прямо противоположное? EC>Хинт. EC>Заметь, этим занимается знатный хаскелист Erik Meijer, такой попсовой штукой как VB и LINQ.
Причем тут LINQ и VB? Ты хоть разберись о чем люди говорят, а потом влезай.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Sinclair wrote: > C>Если честно, мне не хочется вспоминать синтаксис указателей на функции > C>из C, а то бы написал > Всё понятно. Ты заметил, что тебе пришлось поменять содержимое Reduce по > сравнению с первым вариантом?
В первый раз просто лень было писать лишний параметр "self".
> В принципе, задачу можно считать решенной, но в таком виде С немногим > лучше ассемблера. Т.е. тебе пришлось изобрести другой язык в рамках С. > Другой он потому, что не все С конструкции в нем верны. В частности, в > f->func обязательно нужно передавать f, но компилятор за этим проследить > не сможет.
Это не другой язык, скорее программирование в нестандартном стиле.
gandalfgrey wrote: > Таковы производственные требования, однако. Изменить положение вещей — > вне компетенции местного начальства. > ВСЕ сертифицированные для учета приборы используют локальное, в крайнем > случае — московское время.
Ну так и пусть использует. Для отображения. А неонка внутре может и в
UTC работать.
Здравствуйте, Cyberax, Вы писали:
C>Ну так и пусть использует. Для отображения. А неонка внутре может и в C>UTC работать.
Дык ить ! На то и сертификация, чтоб дивайс ВЕСЬ работал в локальном времени. Вкратце — что видим, то и отдаем ( по TCP/IP, RS 485... )
gandalfgrey wrote:
> C>Ну так и пусть использует. Для отображения. А неонка внутре может и в > C>UTC работать. > Дык ить ! На то и сертификация, чтоб дивайс ВЕСЬ работал в локальном > времени. Вкратце — что видим, то и отдаем ( по TCP/IP, RS 485... )
Можно обязать со временем передавать таймзону (или устанавливать глобальную установку дивайса перед обменом данными).
И в прошивке дивайса переводить время туды-сюды, внутре работая исключительно в UTC. Потом объяснить начальству, что
пихать таблицы таймзон в дивайс — идиотизм и заставить переделать требования сертификации.
А так это похоже на проблему с кодировками — передаём поток байт, а потом пытаемся угадать — а какая же кодировка была
использована и 229 это буква "т" или "Р" или ещё чего и как засунуть символы, непомещающиеся в 255 значений?
Решения 2 — использовать одну универсальную кодировку, типа UTF-16, либо передавать значение кодировки каждый раз.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ., Вы писали:
.>Можно обязать со временем передавать таймзону (или устанавливать глобальную установку дивайса перед обменом данными). .>И в прошивке дивайса переводить время туды-сюды, внутре работая исключительно в UTC. Потом объяснить начальству, что .>пихать таблицы таймзон в дивайс — идиотизм и заставить переделать требования сертификации.
Тут есть одно толстое НО : сертифицирует госинспекция по госстандартам. Лезть в дивайс с целью модификации, кстати, тоже запрещено — РАО ЕЭС не понравится, ежели сертифицированный счетчик будет делить все показания на 10...
.>А так это похоже на проблему с кодировками — передаём поток байт, а потом пытаемся угадать — а какая же кодировка была .>использована и 229 это буква "т" или "Р" или ещё чего и как засунуть символы, непомещающиеся в 255 значений? .>Решения 2 — использовать одну универсальную кодировку, типа UTF-16, либо передавать значение кодировки каждый раз.
Я могу согласиться с тем, что это в основном организационная проблема ( как и БОЛЬШИНСТВО других проблем ), но это стандарт. Как там по латыни — сед лекс, дюра лекс ! ( Закон тверд, но таков закон )
А есть еще и отраслевые стандарты, и корпоративные, и уровня предприятия...С тем же временем — в одной конторе 0 часов 0 минут означают следующие сутки, а в другой — предыдущие. И это как-то надо согласовывать...
Здравствуйте, BulatZiganshin, Вы писали:
BZ>не совсем так. использование монад для создания императивного кода — лишь одно из их применений. принципиально, монада — это некий контекст, в котором производятся вычисления. этот контекст может быть, например, текущими обрабатываемыми данными, сообщением об ошибке или выходными данными. без монад это всё нужно передавать либо явными параметрами, либо хранить в глобальных переменных. первое многословно и разрушает абстракцию, второе — бад стайл, и бесполезно при многопоточном программировании
Пусть так. Один фиг для в доску императивного и к тому же объектно ориентированного языка все это не имеет смысла. В LINQ используются банальные лямбды и методы расширения. Последнии это всего лишь синтаксический сахор позволяющий вызывать статические методы (первый параметр которых помечен специальным ключевым словом) как будто они экземплярные:
static class A
{
public int Inc(this int x, int y)
{
return x + y;
}
}
...
Console.WriteLine(123.Inc());
причем тут спрашивается монады?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>SelectMany == bind, имхо, остальные операторы тоже представляют собой монадические комбинаторы.
И при чем тут LINQ? SelectMany это просто статический метод в классе Sequence. То что он extension method, это просто синтаксический сахар.
Вобщем, идея о том, что LINQ это монады на мой вкус кажется крайне странной.
Здравствуйте, VladD2, Вы писали:
BZ>>не совсем так. использование монад для создания императивного кода — лишь одно из их применений. принципиально, монада — это некий контекст, в котором производятся вычисления. этот контекст может быть, например, текущими обрабатываемыми данными, сообщением об ошибке или выходными данными. без монад это всё нужно передавать либо явными параметрами, либо хранить в глобальных переменных. первое многословно и разрушает абстракцию, второе — бад стайл, и бесполезно при многопоточном программировании
VD>Пусть так. Один фиг для в доску императивного и к тому же объектно ориентированного языка все это не имеет смысла.
но ведь именно на это соображение я выше и ответил! представь себе скажем имя лог-файла, которое нужно передавать во все процедуры, поскольку запись в лог-файл может понадобиться где-то в самом низу иерархзии вызовов
Здравствуйте, BulatZiganshin, Вы писали:
VD>>Пусть так. Один фиг для в доску императивного и к тому же объектно ориентированного языка все это не имеет смысла.
BZ>но ведь именно на это соображение я выше и ответил! представь себе скажем имя лог-файла, которое нужно передавать во все процедуры, поскольку запись в лог-файл может понадобиться где-то в самом низу иерархзии вызовов
Здравствуйте, VladD2, Вы писали:
VD>C# не является линивым, и является императивным. В нем вычисления и так импереативныи и последоательны. Монады ему ныжны как рыбе зонтик.
Language Integrated Query (LINQ) is a framework that is rooted
in the theoretical ideas of monads and monad comprehensions to
allow seamless querying over objects, XML, and relational data.
Здравствуйте, VladD2, Вы писали:
VD>C# не является линивым, и является императивным. В нем вычисления и так импереативныи и последоательны. Монады ему ныжны как рыбе зонтик.
Language Integrated Query (LINQ) is a framework that is rooted
in the theoretical ideas of monads and monad comprehensions to
allow seamless querying over objects, XML, and relational data.
VD>>>Пусть так. Один фиг для в доску императивного и к тому же объектно ориентированного языка все это не имеет смысла.
BZ>>но ведь именно на это соображение я выше и ответил! представь себе скажем имя лог-файла, которое нужно передавать во все процедуры, поскольку запись в лог-файл может понадобиться где-то в самом низу иерархзии вызовов
AVK>На то есть паттерн ServiceLocator.
в хаскел-сообществе есть такая мысль, что монады — это наш способ делать паттерны но вообще-то замечу, что паттерн — это методолгия программирования, я же говорю о поддержке этой возможности в языке. для асма тоже есть паттерн ООП-программирования, что не делает его однако хорошим выбором
а в чём конкретно состоит этот паттерн? если скажем в разветвлённой программе неожиланно высняется, что необходимо ещё и логгинг вызывать в некоторых местах, то что вы делаете?
Здравствуйте, EvilChild, Вы писали:
EC>В буквальном смысле (если брать за определение реализацию в Haskell) конечно нет, но идея оттуда. EC>Я не ожидал, что будут читать буквально. EC>Исходный смысл моего поста в том, что монады штука не безполезная и LINQ тому подтверждение.
Монад нет в C#, так как они на фиг не упали в ООЯ. Эта сущьность нужна только чтобы убрать идеологические проблемы ленивого, "чистого" ФЯ.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, BulatZiganshin, Вы писали:
BZ>но ведь именно на это соображение я выше и ответил! представь себе скажем имя лог-файла, которое нужно передавать во все процедуры, поскольку запись в лог-файл может понадобиться где-то в самом низу иерархзии вызовов
Представил. Теперь потрудись объяснить причем тут C#?
В нем есть только два способа передать информацию — это глобальные переменные, и параметры методов.
Ничего нового в C# 3.0 в этом плане не появится.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
BZ>>но ведь именно на это соображение я выше и ответил! представь себе скажем имя лог-файла, которое нужно передавать во все процедуры, поскольку запись в лог-файл может понадобиться где-то в самом низу иерархзии вызовов
AVK>На то есть паттерн ServiceLocator.
Не, скорее паттерн "передача объекта через параметр метода".
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, EvilChild, Вы писали:
VD>>C# не является линивым, и является императивным. В нем вычисления и так импереативныи и последоательны. Монады ему ныжны как рыбе зонтик.
EC>
EC>Language Integrated Query (LINQ) is a framework that is rooted
EC>in the theoretical ideas of monads and monad comprehensions to
EC>allow seamless querying over objects, XML, and relational data.
Здравствуйте, BulatZiganshin, Вы писали:
BZ>т.е. как видите монада используется сначала для перебора значений в некотором источнике, а затем для отсеивания тех, которые нас не устраивают, при этом описание перебираемого набора и условий отбора коструируется последовательно, предложение за предложением. в linq, как я понимаю, используется что-то похожее, и его операции — это statement'ы монады, перебирающие источник данных или отсекающие ненужные значения. не знаю, правда, как group by в это вписан
Замечательно. Но причем тут монады? Это проблемы реализации императивных алгоритмов на Хаскеле. Таких проблем ни в одном ООЯ нет в помине, так как в них есть объекты с изменяемым состаянием.
Здравствуйте, VladD2, Вы писали:
VD>Замечательно. Но причем тут монады? Это проблемы реализации императивных алгоритмов на Хаскеле. Таких проблем ни в одном ООЯ нет в помине, так как в них есть объекты с изменяемым состаянием.
VD>Теперь перечитай еще раз бредовый лозунг EvilChild-а: VD>LINQ это монады для мейнстрима.
Здравствуйте, VladD2, Вы писали:
EC>>В буквальном смысле (если брать за определение реализацию в Haskell) конечно нет, но идея оттуда. EC>>Я не ожидал, что будут читать буквально. EC>>Исходный смысл моего поста в том, что монады штука не безполезная и LINQ тому подтверждение.
VD>Монад нет в C#, так как они на фиг не упали в ООЯ. Эта сущьность нужна только чтобы убрать идеологические проблемы ленивого, "чистого" ФЯ.
Здравствуйте, EvilChild, Вы писали:
EC>Т.е., по твоему, не в чистом ФЯ от них толку нет?
Тольку мало. Они вносят оверхед, трудны для понимания и грязны с теоретической точки зрения (должны выполняться законы, которые не проверить автоматически). Из-за возможности создать неправильную монадуу компилятор не может провести оптимизацию, исходя из общих монадических законов.
Здравствуйте, Quintanar, Вы писали:
EC>>Т.е., по твоему, не в чистом ФЯ от них толку нет?
Q>Тольку мало. Они вносят оверхед, трудны для понимания и грязны с теоретической точки зрения (должны выполняться законы, которые не проверить автоматически). Из-за возможности создать неправильную монадуу компилятор не может провести оптимизацию, исходя из общих монадических законов.
А какие им есть альтернативы в случае чистого ФЯ? Кроме Uniqueness Typing из Clean?
Здравствуйте, BulatZiganshin, Вы писали:
BZ>в хаскеле они тожде не являются частью языка, и для них нет автооптимизаций, связанных с выполнением этих законов. какой удар!
1) В Хаскеле есть типы классов. Без них монады практически бесполезны.
2) Специальная поддержка в GHC есть.
3) Монады все равно даже в GHC вносят тормоза. Бесплатно ничего не бывает.
Здравствуйте, Quintanar, Вы писали:
BZ>>в хаскеле они тожде не являются частью языка, и для них нет автооптимизаций, связанных с выполнением этих законов. какой удар!
Q>1) В Хаскеле есть типы классов. Без них монады практически бесполезны. Q>2) Специальная поддержка в GHC есть.
Речь о do нотации? Q>3) Монады все равно даже в GHC вносят тормоза. Бесплатно ничего не бывает.
Можно подробнее?
Еще забыл добавить — монады антифункциональны. Меня крайне раздражала эта их черта в Хаскеле — как будто не на красивом ФЯ пишешь, а на кривой императивной приблуде. Кстати, ленивые вычисления и монадно-императивный подход не очень-то совместимы.
Здравствуйте, EvilChild, Вы писали:
Q>>2) Специальная поддержка в GHC есть. EC>Речь о do нотации?
Да.
Q>>3) Монады все равно даже в GHC вносят тормоза. Бесплатно ничего не бывает. EC>Можно подробнее?
Скажем, монада, которая имитирует исключения с помощью Nothing/Just. Понятно, что руками писать все эти проверки не надо, но на деле они все равно есть. Исключения, очевидно, работали бы в разы эффективнее и в GHC их таки добавили.
Ну и в целом. Каждая монадная операция — это вызов bind. По коду с виду может быть все красиво, а bind в это время будет отжирать ресурсы — в parsec, вроде, такая проблема.
Самый главный аргумент против — это то, что при интенсивном применении монад код становится императивным и по сути и по виду. Это не может не бесить.
Здравствуйте, Quintanar, Вы писали:
Q>Скажем, монада, которая имитирует исключения с помощью Nothing/Just. Понятно, что руками писать все эти проверки не надо, но на деле они все равно есть. Исключения, очевидно, работали бы в разы эффективнее и в GHC их таки добавили. Q>Ну и в целом. Каждая монадная операция — это вызов bind. По коду с виду может быть все красиво, а bind в это время будет отжирать ресурсы — в parsec, вроде, такая проблема.
Речь об этом (страница 7 последний абзац)?
Q>Самый главный аргумент против — это то, что при интенсивном применении монад код становится императивным и по сути и по виду. Это не может не бесить.
Почему по сути?
BZ>>в хаскеле они тожде не являются частью языка, и для них нет автооптимизаций, связанных с выполнением этих законов. какой удар!
Q>1) В Хаскеле есть типы классов. Без них монады практически бесполезны. Q>2) Специальная поддержка в GHC есть. Q>3) Монады все равно даже в GHC вносят тормоза. Бесплатно ничего не бывает.
первое. монады — это класс Monad, реализуемый в бибилиотеке. написать его может любой желающий, а для monad transformers сейчас вообще две разных библиотеки. поддержка их в языке сводится к правилам трансляции do notation. поддержка в компиляторе — куда значительней. во-первых, function guard компилируется в код, использующий монаду. во-вторых, тип "a-> IO b" на самом деле означает "a -> RealWorld -> (# RealWorld, b #)" и ghc предоставляет оптимизацию представления тпов, делающую её эквивалентной "a->b". что кстати говоря и позволяет объявить например "tell :: Int -> IO Int" хотя в девичестве он имеет тип "int(int)" или что-то типа того. однако это оптимизации универсальные и применяются точно так же к любым unboxed tuple и вероятно любому другому фантомному типу
IO & ST monads, таким образом, тормозов не вносят, а остальные — да. это ж в конце концов просто syntax sugar для скрытной передачи параметров никаких проверок/использований соблюдения monad laws нет и в помине, monadic code после desugaring компилируется как любой другой DSL
Здравствуйте, AndrewVK, Вы писали:
L>>SelectMany == bind, имхо, остальные операторы тоже представляют собой монадические комбинаторы.
AVK>И при чем тут LINQ? SelectMany это просто статический метод в классе Sequence. То что он extension method, это просто синтаксический сахар.
Не понял претензии... А bind это просто метод в классе Monad.
AVK>Вобщем, идея о том, что LINQ это монады на мой вкус кажется крайне странной.
Я воспринял это как взгляд Erik Meijer. Почему бы и нет? Связка есть, монадические законы выполняются.
Здравствуйте, EvilChild, Вы писали:
EC>Т.е., по твоему, не в чистом ФЯ от них толку нет?
Ни малейшего! Это фиговый листок позволяющий сделать вид, что язык действительно чисто-функциональный и ленивый в то время как мир с которым общается язык является императивным.
Та фразу что ты увидил, но не смог осознать, говорила о том, что натолкнуло на мысль запроса по объектам. С тем же успехом их могло натолкнуть на эту мысль что угодно. Просто люди варятся в своих мирах и черпают вдохновение из своих конекстов.
К сведению, в Лиспе похожие запросы были уже много лет.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Quintanar, Вы писали:
Q>Самый главный аргумент против — это то, что при интенсивном применении монад код становится императивным и по сути и по виду. Это не может не бесить.
Я не знаю почему тебя это бесит. Меня лично раздражает, то что люди выдумывают средство эмуляции действительности. Хотя что ее эмулировать?
Казалось бы. Пометь блок кода и скажи, что он должен выполняться последовательно и не лениво. И все! Пиши себе в других местах пользуясь всеми приемуществами линивости, а когда надо просто переключайся в императив. Но нет, мы создаем себе сказку и усилиенно пытаемся поверить в нее. В итоге получаем тоже самое, но сложно, запутано и медленно.
В том же C# ленивость включается итераторами. Не так круто конечно как в Хаскеле, но блин, большинство проблем решается красиво и эффективно! А если бы можно было вот так запросто пометить код как ленивый, то было бы вообще супер.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, EvilChild, Вы писали:
Q>>Самый главный аргумент против — это то, что при интенсивном применении монад код становится императивным и по сути и по виду. Это не может не бесить. EC>Почему по сути?
Потому что монады — это и есть императивыне участки кода, только их очень сильно пытаются замаскировать под офигительно умную идею.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, EvilChild, Вы писали:
EC>А какие им есть альтернативы в случае чистого ФЯ? Кроме Uniqueness Typing из Clean?
На самом деле есть простое и доступное понятие — левивость вычисления.
Как не смешно к чистоте функцинальности оно имеет очень попосредованное отношение. Это деталь реализации. Просто чистый функциональный код куда проще сделать ленивым. Но итераторы C# и континуэшоны Руби отлично показыают, что код может быть ленивым и в императивных языках.
Так вот если код не линивый, то у него есть два важных свойства:
1. Он выполняется четко последовательно.
2. Вычисления не могут "подвиснуть".
Таким образом достаточно сказать, что код не ленивый, и будь он функциоанльным, или не фукнциональным проблем с общением с "внешним миром" возникнуть не может.
Так вот ленивость можно рассматривать как атрибут участка кода. Опять же берем в пример C#-вые итераторы. Функции реализвющие итератор можно считать ленивыми. Их значение отложено. Мы можем написать:
var res = SuperPuperQuary();
но вычисление не произойдет. Оно будет отложено до фактического извлечения результатов.
Можно создать язык (или зименить имеющийся) в котором будет можно просто помечать код неким атрибутом ленивости. Ну, а компилятор в зависимости от этого атрибута будет генерировать ленивый или не ленивый код для соотвествующих участков. Задача эта сложная, но мне кажется, решаемае. В результате мы получим гибридный язык в основе которого лежит простая и понятная идеология, а не зауности.
Кстати, в реальной жизин я бы предпочел иметь язык в котором по умолчанию исполнение было бы не ленивым, но его можно было бы включить пометив неким образом функцию или блок кода. Плюс можно рассматривать ленивыми все генераторы (конструкции вроде [1, 3, ... ]) и возможно что-то еще.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, BulatZiganshin, Вы писали:
BZ>>>но ведь именно на это соображение я выше и ответил! представь себе скажем имя лог-файла, которое нужно передавать во все процедуры, поскольку запись в лог-файл может понадобиться где-то в самом низу иерархзии вызовов
VD>>Представил. Теперь потрудись объяснить причем тут C#?
VD>>В нем есть только два способа передать информацию — это глобальные переменные, и параметры методов. VD>>Ничего нового в C# 3.0 в этом плане не появится.
BZ>самое смешное, что в хаскеле — тоже для записи императивных алгоритмов в pure & lazy языке типа хаскела и clean используется фиктивное значение типа real world, передаваемое в и возвразаемое любой императивной процедурой.
real world — само по себе блулшит еще тот, но главное не это. C# не является pure & lazy. Он вообще не pure и не lazy.
Так что о каких монадах в нем можно вести речь я не пойму. Один прочел фразу, не въехал в нее и понеслась...
BZ>а do предоставляет для этого синтаксический сахар с закосом под императивные языки:
А зачем закос то? Пусть это будет нормальный императивный код. А вот это:
BZ>main = do ch1 <- getChar BZ> ch2 <- getChar BZ> putChar ch1
извни, я кроме как извратом назвать никак не могу.
BZ>а теперь представьте, что вы делаете другую монаду...
Да, мне по барабану монады. Пойми, не все тащатся от того что им имют мозг во все дыры. Кое-кто предпочитают простые и эффктивные решения.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
VD>>Нет это их смысл. А вот области применения определяются этим смыслом.
L>Ну, кроме как посоветовать пойти почитать какие бывают монады мне больше нечего добавить.
Уже читал. И весе применения в конце концов приводят к последователному изменению состояния, т.е. императиву.
VD>>В общем, приведи плиз пример где в ООЯ были бы нужны монады.
L>Давай начну с отмазок — я не говорил, что они нужны в ООЯ, мало того, я даже не говорил, что они в ФЯ нужны
Но полез защищать ахинею о том, что в ООЯ что-то там реализовано на монадах?
L>Но раз ты сказал волшебное слово...
L>Монады можно использовать, например, в качестве альтернативы известным паттернам проектирования. Например, вместо NullObject можно взять мейби-монаду. У этого подхода есть определенные преимущества перед NullObject (впрочем, как и недостатки). В частности, нам не нужен отдельный нуль-объект.
Изивини, но почему в ОКамл и Немрле есть аналогичные решения без монад? Поместил объект в Some(...) и пользуйся, а если нужно извлечь, то паттерн матчинг к твоим услугам.
L>Да, и когда будешь отвечать на этот пример, вспомни, пожалуйста, что я не говорил, что монады "нужны", чтобы мы тут не нафлеймили (а то в последнее время у нас это здорово получается). Но вот обосновать их применение, наверное, можно. Раз уж люди их применяют.
Я вижу, что ты понимашь это. Но я так же вижу, что когда кто-то неразобравшись в вопросе понес ахинею, ты помог ему закрепить его заблуждения.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Казалось бы. Пометь блок кода и скажи, что он должен выполняться последовательно и не лениво. И все! Пиши себе в других местах пользуясь всеми приемуществами линивости, а когда надо просто переключайся в императив. Но нет, мы создаем себе сказку и усилиенно пытаемся поверить в нее. В итоге получаем тоже самое, но сложно, запутано и медленно.
во-первых, там просто нет блоков кода. описания в чисто математическом ключе:
f x = let y = x*2
z = y+3
in y*z
т.е. вставить в такой набор мат. равенств вызовы процедур довольно проблематично. во-вторых, это потребовало бы больших переделок в языке и компиляторах, поскольку нарушило бы чистоту языка и независимость результата от порядка вычислений. т.е. пришлось бы вводить спец. правила взаимодействия императивного и чистого кода. фактически это и было сделано, но не на уровне изменения описания языка, а на уровне описания всех необходимых изменений средствами самого хаскела. и этот realWorld — это как раз и есть описание семантики императивных вычислений средствами семантики функциональной. и возмущаться этим — всё равно что предъявлять претензии к математикам вообще, которые придумывают столь сложные теории для описания того, как яблоки падают на землю (ты в курсе, что матанализ появился именно для описания движения планет по круговым орбитам?)
Last Cjow Rhrr wrote: >
> И что самое интересное, подобная возможность уже в Хаскеле есть — это > FFI. Вот мне любопытно, что такого плохого станется, если поднять > императив на уровень языка и использовать его в ограниченном контексте? > Это несколько некомфортно с идеологической точки зрения, но практически > полезно. > > ps: (боже мой!!! неужели это сказал я!!! ААААА!!!)
Я не понял, чем твое предложение отличается от уже имеющейся монады ST.
Не развернешь мысль?
Last Cjow Rhrr wrote: >> > Вот мне любопытно, что такого плохого станется, если поднять >> > императив на уровень языка и использовать его в ограниченном контексте? > > PM>Я не понял, чем твое предложение отличается от уже имеющейся монады ST. > PM>Не развернешь мысль? > > Хочется внутри таких "преобразователей состояния" использовать обычное > структурное программирование с обычными управляющими конструкциями.
, как легко
такие конструкции определить. Для применения в ограниченном контексте
вполне подходит. Гипотетические проблемы с лифтингом, которые мы
обсуждали ниже, возникнут, если этот ограниченный контекст раздуть, и в
этом случае действительно желательно рассмотреть вариант с FFI. Иметь 2
яызка в одном — не слишком хорошая идея, IMHO.
Здравствуйте, lomeo, Вы писали:
AVK>>И при чем тут LINQ? SelectMany это просто статический метод в классе Sequence. То что он extension method, это просто синтаксический сахар.
L>Не понял претензии... А bind это просто метод в классе Monad.
И что? Как это доказывает утверждение о сходстве LInQ и монад?
AVK>>Вобщем, идея о том, что LINQ это монады на мой вкус кажется крайне странной.
L>Я воспринял это как взгляд Erik Meijer. Почему бы и нет? Связка есть, монадические законы выполняются.
Здравствуйте, BulatZiganshin, Вы писали:
AVK>>На то есть паттерн ServiceLocator.
BZ>в хаскел-сообществе есть такая мысль, что монады — это наш способ делать паттерны
По поводу паттернов и их уместности здесь был топик, который начинался с сообщения о том, что паттерны суть недоделанность языка. Я там по этому поводу свое мнение уже высказывал. Повторяться не хочу.
BZ>а в чём конкретно состоит этот паттерн? если скажем в разветвлённой программе неожиланно высняется, что необходимо ещё и логгинг вызывать в некоторых местах, то что вы делаете?
Получаем в нужных местах сервис логгера и используем его. Логгер, кстати, чуть ли не хрестоматийный пример этого паттерна.
AVK>>>На то есть паттерн ServiceLocator.
BZ>>в хаскел-сообществе есть такая мысль, что монады — это наш способ делать паттерны
AVK>По поводу паттернов и их уместности здесь был топик, который начинался с сообщения о том, что паттерны суть недоделанность языка. Я там по этому поводу свое мнение уже высказывал. Повторяться не хочу.
да, так имхо и есть. есть методология программирования. есть язык. всё, что есть в этой методологии, но нет в конкретном языке, и становится паттернами программирования, рефакторинга, whatever
BZ>>а в чём конкретно состоит этот паттерн? если скажем в разветвлённой программе неожиланно высняется, что необходимо ещё и логгинг вызывать в некоторых местах, то что вы делаете?
AVK>Получаем в нужных местах сервис логгера и используем его. Логгер, кстати, чуть ли не хрестоматийный пример этого паттерна.
я и написал, что у нас есть два метода — либо всюду тащить это как параметр, либо сделать глобальным сервисом/переменной/whatever. фишка в том, что разные вычисления (например, разные треды) могут использовать два разных логгера. или парсить/генерить две разных программы. или вести сериализацию в два разных участка памяти. и тут ты натыкаешься на глобальные переменные в том или ином виде со всеми вытекающими последствиями. thread-local variables это обычно решают, но это всё обходной путь. монады как раз позволяют передавать параметры во все подчинённые процедуры, но делать это прозрачно, без изменения исходного кода. и позволяют при смене набора используемых "сервисов" просто обернуть код в ещё одну лишнюю монаду без разлборки с вновь появившимся параметром на всех уровнях
palm mute,
>> Хочется внутри таких "преобразователей состояния" использовать обычное >> структурное программирование с обычными управляющими конструкциями.
PM>Ты же сам видел
, как легко PM>такие конструкции определить. Для применения в ограниченном контексте PM>вполне подходит. Гипотетические проблемы с лифтингом, которые мы PM>обсуждали ниже, возникнут, если этот ограниченный контекст раздуть, и в PM>этом случае действительно желательно рассмотреть вариант с FFI.
+1, к сожалению. И поэтому я понимаю и разделяю Евгения и других активных пользователей С++ — у них такой проблемы нет. Пусть им тяжелее взбираться по "абстрактной лестнице" (перекладины шатаются, гвозди царапают мясо, сама лестница обладает нетривиальными топологическими свойствами и норовит завязаться в узел или образовать ленту Мёбиуса), но они могут в случае чего, контролировать поведение программы вооружившись микроскопом и делая отверстия для крепления подковы в перерывах между сердцебиениями. В принципе.
PM>Иметь 2 яызка в одном — не слишком хорошая идея, IMHO.
Хм. Отличие стиля от языка в одном и том же языке от меня ускользает...
Здравствуйте, BulatZiganshin, Вы писали:
BZ>я и написал, что у нас есть два метода — либо всюду тащить это как параметр, либо сделать глобальным сервисом/переменной/whatever. фишка в том, что разные вычисления (например, разные треды) могут использовать два разных логгера. или парсить/генерить две разных программы. или вести сериализацию в два разных участка памяти. и тут ты натыкаешься на глобальные переменные в том или ином виде со всеми вытекающими последствиями.
Здравствуйте, 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>что-то я не понимаю. если два треда одновременно будут сериализовать одну структуру в разные места, то тут как раз и проявится то, что это сервис является аналогом глобальной переменной, верно?
Это если экземпляр сервиса будет один. А если будут разные экземпляры на поток?
BZ>>что-то я не понимаю. если два треда одновременно будут сериализовать одну структуру в разные места, то тут как раз и проявится то, что это сервис является аналогом глобальной переменной, верно?
AVK>Это если экземпляр сервиса будет один. А если будут разные экземпляры на поток?
это и есть global state на уровне треда. недостатки — не сможет справиться с ситуацией, когда работают несколько объектов, которым нужны разные контексты (в случае использования continuations, lazy evaluation), нет статической проверки того, что используются только включённые в данный момент интерфейсы. но по большому счёту это вполне терпимый вариант и я не сомневаюсь, что либо через thread-local state, либо через параметры это всегда и реализуется
Здравствуйте, BulatZiganshin, Вы писали:
BZ>это и есть global state на уровне треда.
Только в случае, если сервис опубликован в корневом сервис-менеджере. А если не в корневом, то только в пределах его контекста. А дальше все уже зависит от конкретного приложения. Монады тут ничего не меняют, бо проблема логическая, а не технологическая.
Здравствуйте, 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
Здравствуйте, palm mute, Вы писали:
>> Контекст еще есть. И не обязательно это TLS. PM>Каким образом этот контекст попадает в точку вызова сервиса?
Передается в параметрах метода или параметрах конструктора например. Зависит от конкретной архитектуры конкретной системы.
PM>Я PM>пробежался по описанию Фаулера, но сути не уловил.
Да, к сожалению более доходчивых описаний я в инете не видел.
PM> Ну, есть синглтон
Синглтон это как раз не очень правильно.
PM>с PM>хэш-таблицей именованных объектов-сервисов (их еще и кастить надо, PM>тьфу)
Чтобы не кастить есть дженерики
PM>, дальше что? Кто и как обеспечивает деление на уровни и доставку PM>контекста, в двух словах?
Деление на уровни обеспечивается архитектором системы. Про контекст я написал выше.
AndrewVK wrote: > > >> > Контекст еще есть. И не обязательно это TLS. > PM>Каким образом этот контекст попадает в точку вызова сервиса? > > Передается в параметрах метода или параметрах конструктора например. > Зависит от конкретной архитектуры конкретной системы.
Так об этом же и говорил Булат. С помощью монад можно избавиться от
передачи в аргументах метода или конструктора.
Здравствуйте, 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>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, BulatZiganshin, Вы писали:
BZ>честно говоря непонятно, что конкретно ты предлагаешь. в хаскеле и так уже есть чистые функции и, назовём их так, "процедуры". последние работают в IO monad. далее, функция не может вызывать процедуру, всё остальное возможно. таким образом, транзитивное замыкание приводит к тому, что внутри чистого кода может выззываться только чистый код (с поправкой на ST и тому подобные монады), а внутри императвиного — вс что угодно
Замечательно! Вот только это так можно сделать в любом языке! Надо только ввести пометку блоков кода как чисто функнциональные.
Проблема Хаскеля лишь в ленивости. Ведь если из ленивого кода вызвать императивный, то можно получить UB. Ведь код может не выполниться когда надо.
Меж тем линивость нужна далеко не всегда. Болшинство вычислений прекрасно пройдут в обычном ключе. Более того если программист сам будет определять, что лениво, а что нет, то и проблем у него не возникнет.
Почему в C# я пишу итератор в совершенно императивной манере:
IEnumerable<int> Seq(int start, int end)
{
for (int i = start; i <= end; i++)
yield return i;
}
и не получаю никаких пробелм (ни физический, ни идеологических)?
BZ>на уровне языка "процедуры" имеют тип (... -> IO a). в "IO Inside" описано как механизм типов делает невозможным выщов процедур из функций (окромя испольщования unsafePerformIO)
Это самовнушение. Физически проблем вызова "чистым кодом" "не чистого" нет. Ее придумали пуристы. И доказано это на практике.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Некоторые монады вовсе не предназначены для изменения состояния. L>Некоторые не предназначены для последовательного исполнения.
И что они тогда делают?
L>Простой пример — монада списка.
Тот же вопрос.
L>Ну, если на самом деле интересна моя мотивация, то она примерно такова. L>Ты назвал человека некомпетентным, теперь называешь его мнение ахинеей. Я так не считаю, так почему бы не вложить свои 5 копеек?
Потому что когда тебя начинпшь расспрашивать, то выясняется, что ты подтверждаешь мои слова.
VD>>Изивини, но почему в ОКамл и Немрле есть аналогичные решения без монад? Поместил объект в Some(...) и пользуйся, а если нужно извлечь, то паттерн матчинг к твоим услугам.
L>Тут может быть много ответов. Но все они поведут к флейму. Я попытался обощить ниже.
Ответы про монады, как сами монады — аморфны и выскальзают из рук. Никогда не получишь прямого и однозначного ответа.
L>Попробую донести свою мысль. Всё нижеследующее — это моё имхо. Монады — абстрактное понятие.
Классы/варинаты тоже. И что?
L> В том смысле, что это гораздо абстрактнее понятия конкретного паттерна.
Та же фингя.
L> Вот когда я описывал альтернативу для NullObject — я взял конкретную монаду.
А я конкретный вариант. И что?
L> Т.е. говорить об использовании монады без указания конкретной монады, это почти как говорить об использовании паттерна без указания конкретного.
Не совсем. Говорить о паттернах как раз можно. А вот монады снова слишком склизки для этого.
L> "Почти" — потому что польза от этого всё таки есть. В силу того, что все они подчиняются определенным правилам, т.е. понятие достаточно формализовано.
ОК. Я не хаскель-хакер и многое в нем не понимаю. Опиши эти правила как ты их ивдишь. За одно объясни какой в них смысл в языках где есть классы, объекты, варианты, их методы позволяющие менять их состояние...
L>Для того, чтобы на некоторое решение можно было бы взглянуть как на монадическое, достаточно, чтобы это решение соотвествовало нескольким правилам.
В эти правла не входит случаяно накомпление/изменение состояния?
L>Если не объявлять — мы все равно можем заметить этот интерфейс, если он есть. И сделать для себя определенные выводы.
У меня уже есть интерфейсы и типы. Зачем мне малопонятная сущьность с горой булшита вместо простых и понятных вещей?
L>Для тебя монада — это исключительно IO/State, которые, действительно, эмулируют императив. Эти монады в ИЯ не нужны.
Нет. Для меня монады — это совсем другое. Я вижу монады как подпорку под несостоятельной идеей чистоты. Они просто не нужны в "грязном", но реальном мире — мире где есть состояние и последовательность действий. В мире где прежде чем выпить чай нужно вскипятить воду и заварить заварку, а не где чай кипятится и заваривается когда я опракидываю пустую чашку себе в рот.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mirrorer, Вы писали:
M>Понятное дело что для языков, в которых массивы были отродясь Array реализованный через IList выглядит по меньшей мере извращением и мозго.. в общем brainfuck-ом. Но это не значит что сама идея интерфейса IList ущербна, и что классы List, Queue, Dictionary не нужны в языке поддерживающием массивы.
Дело в том, что в языках где "массивы были отродясь Array реализованный через IList" если бы их и не было, то их все равно реализовали бы через IList в виде класса. Так что вместо загадочных монад там есть объекты с состояниями которые решают все проблемы. А массивы захардкожены для эффективности.
M>Монада это интерфейс. КАК его использовать — личное дело каждого. И какие классы будут реализовывать этот интерфес в целом неважно. Важно то, что они будут иметь унифицированный интерфейс.
Я не спорю. Вот только в Хаскеле уже есть аналог интерфейса — это классы типов. Вот они спроектированы изумительно. И то что кроме них потребовались монады говорит о наличии проблем в идеологии.
Так вот в ИЯ таких проблем нет, а стало быть не нужны такие подпорки.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, BulatZiganshin, Вы писали:
BZ>я и написал, что у нас есть два метода — либо всюду тащить это как параметр, либо сделать глобальным сервисом/переменной/whatever. фишка в том, что разные вычисления (например, разные треды) могут использовать два разных логгера. или парсить/генерить две разных программы. или вести сериализацию в два разных участка памяти. и тут ты натыкаешься на глобальные переменные в том или ином виде со всеми вытекающими последствиями. thread-local variables это обычно решают, но это всё обходной путь. монады как раз позволяют передавать параметры во все подчинённые процедуры, но делать это прозрачно, без изменения исходного кода. и позволяют при смене набора используемых "сервисов" просто обернуть код в ещё одну лишнюю монаду без разлборки с вновь появившимся параметром на всех уровнях
В ООП для этого есть классы. Создал класс и все его методы получают неявный контекст. Зачем изобретать велосипед?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, BulatZiganshin, Вы писали:
BZ>и все объекты, вложенные в x, выполняя обычную операцию put, будут лить данные туда, куда им указали. с этим же паттерном, как я понимаю, надо настраивать этот сервис в *каждом* из сериализуемых объектов, входящих в x
Ну, и почему было не объявить интерфейс сериализации (IStream, например) вместо извращений и неявной магии? Далее реализуй его как FileStream или MemryStream и получай себе свой полиморфизм.
Хотя конечно вопрос риторический. Ведь в Хаскеле просто нельзя создать императивный объект. Вот и вынужден он паковать императивные объекты в монады. А в ООЯ то зачем это делать? Мы просто создаем нужный класс и все.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, palm mute, Вы писали:
PM>Так об этом же и говорил Булат. С помощью монад можно избавиться от PM>передачи в аргументах метода или конструктора.
Спомощью полей объекто, тоже.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mirrorer, Вы писали:
M>Монада это интерфейс. КАК его использовать — личное дело каждого. И какие классы будут реализовывать этот интерфес в целом неважно. Важно то, что они будут иметь унифицированный интерфейс.
Почему-то этому интерфейсу приписывают какую-то магическую сверхценность. Например, моноид тоже обладает офигительной общностью. Можно было бы сделать унифицированный интерфейс (plus,zero) для
чисел plus= +; zero = 0
списков plus= ++; zero = nil
функций plus= .; zero = id
преобразователей состояний итд.
но будет ли от того медведю польза и удовольствие?
Здравствуйте, BulatZiganshin, Вы писали:
BZ>выглядит простой и ясной. а большинству людей, обученных императивному программированию, удобней и понятней запись в виде цикла. третьи же предпочитают higher-order funcs и запишут это в виде:
Угу, а тех кто запишет так (а главное будет думать в терминах подмен ):
VD>Я не спорю. Вот только в Хаскеле уже есть аналог интерфейса — это классы типов. Вот они спроектированы изумительно. И то что кроме них потребовались монады говорит о наличии проблем в идеологии.
Дык монады и реализованы на основе классов типов. Можешь считать монады патерном ФП.
Вот допустим при помощи монады List очень просто делаются list comprehensions. Разве это плохо?
Да, list comprehensions можно реализовать туевой хучей способов. Но решение на основе монад выглядит красиво имхо
Все три определения равносильны. Просто одни подсахарены больше другие меньше.
И второе имхо выглядит весьма достойно и понятно. А это ничто иное монада List.
Здравствуйте, Трурль, Вы писали:
Т>Почему-то этому интерфейсу приписывают какую-то магическую сверхценность.
Тут +10 я тоже не очень понимаю почему именно этот интерфейс раскручивается..
И почему его объяснение зачастую переусложенено.. Ведь большинство людей приходят в Хаскел из обычных императивных языков, и грузить им голову теорией категорий и говорить что "монады это уууу" не есть хорошо. Конечно на основе этого интерфейса можно навернуть очень сложные конструкции но для введения достаточно аналогии с IMonad<T>.
Но у меня мало опыта по работе с монадами, поэтому сложно что-то сказать, вот как (если) расковыряю Parsec, возможно увижу то, чего не видел раньше...
Т>Например, моноид тоже обладает офигительной общностью. Можно было бы сделать унифицированный интерфейс (plus,zero) Т>но будет ли от того медведю польза и удовольствие?
Наверное от задачи зависит ...
ИМХО. Монады — это паттерн ФП. Я думаю что не единственный. Просто так сложилось что вокруг него больше всего непоняток возникает.. Почему —
Здравствуйте, BulatZiganshin, Вы писали:
BZ>это вы рассужаете о своём паттерне. в моём примере использования монад речь шла о другом. есть универсальная процедура сериализации. куда сериализировать — она узнаёт из контекста вызова, т.е. из тех самых параметров. монады позволяют передавать эти паораметры неявно на всю глубину вызовов
То есть если я правильно понял, в данном случае аналогом в импетаривном языке будет дополнительный параметр у каждой процедуры по всей иерархии вызовов?
что-то типа
public void SomeAction(smth, context)
{
SomeAction1(smth, context);
}
public void SomeAction1(smth, context);
{
SomeAction2(smth, context);
}
public void SomeAction2(smth, context);
{
SomeAction3(smth, context);
}
public void SomeAction3(smth, context);
{
smth.Serialize(context);
}
Причем Context это что-то типа хеш таблицы куда можно запихивать сколько угодно барахла, и нужный кусок барахла будет использован на уровне для него предназначенном?
VD>>Твои "сервисы" не более чем развитие идеи "супер навороченной глобальной переменной"
ANS>Это называется "переменная с динамической областью видимости".
точно, можно и так это сделать. но как я понимаю, ни в одном из рассматриваемых нами языков их нет
Здравствуйте, palm mute, Вы писали:
PM>Mirrorer wrote:
>> Все три определения равносильны. Просто одни подсахарены больше другие >> меньше. PM>Вот четвертое: PM>
PM>(C) lomeo >> И второе имхо выглядит весьма достойно и понятно. А это ничто иное >> монада List. PM>Выглядит ни грамма не понятно, и это все та же монада List .
это как раз самое понятное, и тип у него на самом деле более общий:
cartesian3 :: Monad m => m a -> m b -> m c -> m (a,b,c)
(впрочем, у остальных вариантов тип такой же)
в данном случае монаду надо представлять как контейнер, а эту операцию — как возврат контейнера, получающего 3 контейнера, содержащие соответственно a, b и с, и возвращаюшего контейнер, содержащий тройку (a,b,c)
если это контейнер — IO, то процелдура просто агрегирует результаты трёх IO операций. если List — то все возможные тройки. если Maybe — то Just (a,b,c) если все контейнеры содержали Just, и Nothing иначе
Здравствуйте, VladD2, Вы писали:
VD>Ответы про монады, как сами монады — аморфны и выскальзают из рук. Никогда не получишь прямого и однозначного ответа. :)
Увы, почему то монады сложны для первоначального понимания (тяжело врубиться, грокнуть). Хотя по сути они просты.
L>> Т.е. говорить об использовании монады без указания конкретной монады, это почти как говорить об использовании паттерна без указания конкретного.
VD>Не совсем. Говорить о паттернах как раз можно. А вот монады снова слишком склизки для этого.
Ну, говорить то можно о чём угодно.
L>> "Почти" — потому что польза от этого всё таки есть. В силу того, что все они подчиняются определенным правилам, т.е. понятие достаточно формализовано.
VD>ОК. Я не хаскель-хакер и многое в нем не понимаю. Опиши эти правила как ты их ивдишь. За одно объясни какой в них смысл в языках где есть классы, объекты, варианты, их методы позволяющие менять их состояние...
Правила — это три закона монад + алгебра монадических функций. Для второго можно хотя бы привести знаменитый и очень полезный пример — m >>= f === join (fmap f m). Правила определяют семантику монад, т.е. у нас есть её явная формализация, а это вещь далеко не бесполезная.
Вопрос про смысл монад в ОО несколько размыт. Я не говорил об их явном использовании. Я говорил о взгляде на некоторое решение, как на использующее монаду. Прочитав первый раз книгу о паттернах проектирования, я подумал — блин, да я же всегда так делал. Однако, формализация (ну, более-менее) и абстракция понятия конкретного паттерна помогли мне в дальнейшей работе, т.к. во-первых, я мог определять условия применения явно, а не интуитивно, как раньше, во-вторых, мог использовать паттерн осознанно, а не тратя время на его очередное изобретение. Ну, все прелести формализации в общем.
L>>Для того, чтобы на некоторое решение можно было бы взглянуть как на монадическое, достаточно, чтобы это решение соотвествовало нескольким правилам.
VD>В эти правла не входит случаяно накомпление/изменение состояния?
В данном случае — это три закона. Так что не входит.
L>>Если не объявлять — мы все равно можем заметить этот интерфейс, если он есть. И сделать для себя определенные выводы.
VD>У меня уже есть интерфейсы и типы. Зачем мне малопонятная сущьность с горой булшита вместо простых и понятных вещей?
Это решать тебе. Видимо, незачем, если судить по тому, что ты считаешь монады сложной, непонятной горой булшита :-)
L>>Для тебя монада — это исключительно IO/State, которые, действительно, эмулируют императив. Эти монады в ИЯ не нужны.
VD>Нет. Для меня монады — это совсем другое. Я вижу монады как подпорку под несостоятельной идеей чистоты. Они просто не нужны в "грязном", но реальном мире — мире где есть состояние и последовательность действий. В мире где прежде чем выпить чай нужно вскипятить воду и заварить заварку, а не где чай кипятится и заваривается когда я опракидываю пустую чашку себе в рот.
Здорово, очень хорошая аналогия :-) Только она подходит к ленивым вычислениям вообще.
Что касается "подпорки под несостоятельной идеей чистоты" — так это то же самое, что сказал я — для тебя монада это IO/State. Реализация императива на чистом языке. Ты говоришь обо всех монадах, а подразумеваешь конкретную.
Здравствуйте, BulatZiganshin, Вы писали:
BZ>это вы рассужаете о своём паттерне. в моём примере использования монад речь шла о другом. есть универсальная процедура сериализации. куда сериализировать — она узнаёт из контекста вызова, т.е. из тех самых параметров. монады позволяют передавать эти паораметры неявно на всю глубину вызовов
Ну а контекст позволяет неявно на всю глубину передавать сервисы. Понимаешь, все равно надо что то сделать явно — передать контекст или использовать монаду. Главное, насколько сложно это все будет поддерживать потом.
BZ>ну а назвать serialization target сервисом и потом говорить, что это часть арзитектуры системы, за которую никак не меньше чем архитектор отвечает — это как раз попытка натянуть какой-нибудь из знакомых паттернов туда, где он похож на нужное только отдалённо
Здравствуйте, VladD2, Вы писали:
VD>Ты просто пришел с тем что тебя волнует.
Про ужасную сложность передачи логгера внутрь кода без монад не я рассказывать начал, так что притензии не ко мне. У меня с логгером никогда никаких проблем не было.
BulatZiganshin wrote:
> > это как раз самое понятное, и тип у него на самом деле более общий: > > cartesian3 :: Monad m => m a -> m b -> m c -> m (a,b,c) > > (впрочем, у остальных вариантов тип такой же) > > в данном случае монаду надо представлять как контейнер, а эту операцию — > как возврат контейнера, получающего 3 контейнера, содержащие > соответственно a, b и с, и возвращаюшего контейнер, содержащий тройку > (a,b,c) > > если это контейнер — IO, то процелдура просто агрегирует результаты трёх > IO операций. если List — то все возможные тройки. если Maybe — то Just > (a,b,c) если все контейнеры содержали Just, и Nothing иначе
Я-то как раз это понимаю .
В этом форуме часто Хаскель всплывает, его то превозносят, то обзывают
нехорошим словом "булшит", но знает мало кто.
А мое предыдущее сообщение — просто хулиганская выходка.
Здравствуйте, palm mute, Вы писали:
PM>В этом форуме часто Хаскель всплывает, его то превозносят, то обзывают PM>нехорошим словом "булшит", но знает мало кто.
Ну, если быть точным, то Хаскель булшитом не обзывают.
Речь о монадах :-)
BZ>>это вы рассужаете о своём паттерне. в моём примере использования монад речь шла о другом. есть универсальная процедура сериализации. куда сериализировать — она узнаёт из контекста вызова, т.е. из тех самых параметров. монады позволяют передавать эти паораметры неявно на всю глубину вызовов
AVK>Ну а контекст позволяет неявно на всю глубину передавать сервисы. Понимаешь, все равно надо что то сделать явно — передать контекст или использовать монаду. Главное, насколько сложно это все будет поддерживать потом.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, BulatZiganshin, Вы писали:
BZ>>там вообще-то и описывается эта "сложность поддержки" в случае монад
AVK>Знаешь, такое ощущение, что я разговариваю с глухим. Где я писал что монады сложно поддерживать?
"Понимаешь, все равно надо что то сделать явно — передать контекст или использовать монаду. Главное, насколько сложно это все будет поддерживать потом."
(а у меня — что с маразматиком ничего личного, просто сначала вы говорите что это закладывается в архзитектуру системы, а потом — что архитектор не при чём, сначала что передавать ничего не нужно, потом — что этот логгер зашивается в параметры процедуры или коснтруктора. думаю, что задача всё же существует, и от того, что её назвали паттерном или частю архзитектуры, она не исчезнет. у вас просто набита рвука в её решении, и поэтому вы не замечаете то, что её можно вообще не решать, встроить это решение в сам язык/библиотеку. всё равно, что фортранщик будет говорить, что рексурсия не нужна, поскольку он её уже привык эмуцлировать, ни о чём не задумываясь)
Здравствуйте, BulatZiganshin, Вы писали:
BZ>"Понимаешь, все равно надо что то сделать явно — передать контекст или использовать монаду. Главное, насколько сложно это все будет поддерживать потом."
Ну и?
BZ>(а у меня — что с маразматиком ничего личного, просто сначала вы говорите что это закладывается в архзитектуру системы,
Естественно.
BZ> а потом — что архитектор не при чём
Я этого не говорил. Архитетктор очень даже причем.
BZ>, сначала что передавать ничего не нужно, потом — что этот логгер зашивается в параметры процедуры или коснтруктора.
Опять я не говорил, что логгер зашивается в параметры процедуры.
BZ> у вас просто набита рвука в её решении, и поэтому вы не замечаете то, что её можно вообще не решать
То есть явное использование монад это "можно не решать"? Опять же, я же ясно написал — контекст сам по себе в вертикально интегрированных системах полезен. Наконец, тебе же сказали, что в ООП есть еще и поля/свойства объекта. Говоря об архитектуре я имел ввиду не то, что тут надо специальную архитектуру делать, а то что конкретный способ воплощения паттерна зависит от остальной архитектуры системы. Есть явно выделенный контекст — удобно сделать иерархию service providers поверх него, нет, значит лучше использовать другие структуры — объектный граф, каналы сообщений и т.п. И никакого преимущества монад я здесь не вижу — их все равно надо явно использовать. Да и не может быть тут никаких преимуществ — проблема вертикальной интеграции слоев это не технологическая проблема и не проблема алгоритмов, это проблема архитектурная, и никакие языковые выверты их легко и просто решить не в состоянии, не тот порядок.
Здравствуйте, Трурль, Вы писали:
Т>Почему-то этому интерфейсу приписывают какую-то магическую сверхценность. Например, моноид тоже обладает офигительной общностью. Можно было бы сделать унифицированный интерфейс (plus,zero) для Т>чисел plus= +; zero = 0 Т>списков plus= ++; zero = nil Т>функций plus= .; zero = id
Ага, есть такой, MonadPlus называется.
Т>но будет ли от того медведю польза и удовольствие?
Медведу точно будет.
Здравствуйте, deniok, Вы писали:
D>Физически проблемы взятия адреса переменной в памяти и доступа к ней по этому адресу тоже нет. И кто тут ругает C++ за такую возможность? А после запрета доступа по адресу наворачиваются всякие value- и ref-типы, boxing и unboxing. Казалось бы, объект — это просто кусок памяти, неважно какой (стек, куча).
Физической проблемой является нарушение типобезопасности. Он приводит к самым что нинаесть реальным проблемам. А вот запрет вызова императивного кода "чистым" и наоборот кроме как пуританством болше оправдать нечем.
D>Позволь всё-таки существовать функциональным языкам, а не только смешанным.
Да, сколько угодно. Пусть толко появится хоть один. А то каждый чистый язык обязательно имеет грязные костыли.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mirrorer, Вы писали:
M>Вот собственно и все. M>There is no spoon.
Видимо в этом месте все вокруг должны начать хлопать в ладоши и восклицать "ах как это великолепно". Вот только есть только один обрдованный который часто радуется за компанию. Не исключу, что к нему присояденятся разные ИвилЧилды и им подобные.
Но мне что-то не радостно. Я вспоминаю принцип Оккама. И я вижу только одно. Вы пытаетесь объяснить простые вещи введением лишней для императивных ООЯ сущностей.
Я не спорю, в Хаскеле с его догматами монады вещь нужная. Но я так и не услышал разумного обяснения того зачем эту сущность не то что вводить в ООЯ, но даже употреблять для объясениях тех или иных концепций?
M>В качестве примера рекурсии часто используется вычисление факториала. Но без tail оптимизации оно значительно менее эффективно чем императивное решение в лоб. Однако это не значит что сама идея рекурсии ущербна.
Не улавливаю тут логической связи.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
EC>>The first order of business was to establish the following goals for the language: EC>>1. It should be suitable for teaching, research, and applications, including building large systems. EC>>2. It should be completely described via the publication of a formal syntax and semantics. EC>>3. It should be freely available. Anyone should be permitted to implement the language and distribute it to whomever they please. EC>>4. It should be usable as a basis for further language research. EC>>5. It should be based on ideas that enjoy a wide consensus. EC>>6. It should reduce unnecessary diversity in functional programming languages. More specifically, we initially agreed to base it on an existing language, namely OL.
VD>Думаю ты на настолько глуп чтобы думать, что я приписывал эти черты Хаскелю.
Будь любезен пиши без ошибок, хотя бы когда пытаешься обсуждать чью-то глупость/неглупость, а то тебя можно неправильно понять.
VD>Авторам этого языка к сожалению не удалось создать язык отвечающий этим требованиям.
Что именно из этого списка не удалось? Можешь аргументировать?
VD>Хаскель интуитивен только узкому кругу людей с математиким бэкэндом. Меж тем программирование уже давно вышло за рамки математики.
Где ты там интуитивность среди целей увидел?
EC>>Haskell и есть та экспериментальная площадка, на которой обкатываются идеи, которые попадают в мейнстрим. VD>Ты внимательно читал то что я написал прежде чем отвечать? Или у тебя прицип в жизни такой отчечать все что угодно лиш бы оно не имело никакого отношения к словм оппонентов?
Давай ты оставишь в покое мои припницы. Почему ты вместо ответа на вопрос постоянно переходишь на личности?
VD>Слова "query monad, как в HaskellDB, над которым, кстати, он работал" вообще каша какая-то. Какое отношение "query monad" из HaskellDB имеет к C#. И какое отношение между сравнением чего-то с чем-то из другого языка имеет к наличию этого в другом языке? И соттвественно оправданию лозунгов вроде "LINQ это монады для мейнстрима."?
собственно, LINQ, как и HaskellDB — интерфейс к БД. в HaskellDB для этого использована специальная монада, которая позволяет пошагово уточнить выполняемый запрос, т.е. ты можешь написать что-то вроде:
selectFrom "table" >>= groupBy "order" >>= ...
и >>= будет стратегией вычислений, формирующей из отдельных вызовов выполняемый оператор sql. в linq, вероятно, точно так же
Здравствуйте, BulatZiganshin, Вы писали:
BZ>сам представь, что проще — вызвать одну функцию на верхнем уровне (запустить эту монаду) или добалвять во _все_ объекты то или иное свойство?
"Проще", не значит "лучше". Проще натыкать глобальных переменных или еще какую-нить фигню спароть. Но код пишется не для выброса. Его потом читать и поддерживать надо. И тут в первую очередь важна понятность.
По мне так положить ссылку в объект не так сложно и не вызвает никаких проблем.
Кроме того есть такие вещи как замыкания. В том же Немерле я обычно реализую алгоритм в виде логальных функций которые позволют делать замыкания на внешний контекс. Передовать при этом ничего не надо. И выглядит просто и понятно. По сути классы и их поля это тоже замыкания. Так что не вижу надобности в шаманстве.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, BulatZiganshin, Вы писали:
BZ>>сам представь, что проще — вызвать одну функцию на верхнем уровне (запустить эту монаду) или добалвять во _все_ объекты то или иное свойство?
VD>"Проще", не значит "лучше". Проще натыкать глобальных переменных или еще какую-нить фигню спароть. Но код пишется не для выброса. Его потом читать и поддерживать надо. И тут в первую очередь важна понятность.
вот именно! как раз монады и позволяют сделать это прозрачно
VD>По мне так положить ссылку в объект не так сложно и не вызвает никаких проблем.
на каждую операцию, для которой может понадобиться контекст? такое решение быстро вырастает в сложную архитектуру, как раз и описанную Фаулером. монады же позволяют сделать это средтствами самого языка, а не тщательно проработанного и аккуратно выполняемого паттерна дизайна. так что ещё раз повторюсь, паттерны — это разница между выбранной методолгией программирования и средствами, предоставляемыми непосредственно языком. в каких-то языках нужны паттерны рекурсивного вызова, ООП, синхронизации тредов, организации higher-order functions. в каких-то они являются частью языка или бибилиотек
VD>Кроме того есть такие вещи как замыкания. В том же Немерле я обычно реализую алгоритм в виде логальных функций которые позволют делать замыкания на внешний контекс. Передовать при этом ничего не надо. И выглядит просто и понятно. По сути классы и их поля это тоже замыкания. Так что не вижу надобности в шаманстве.
представьте себе сериализатор объекта. он рекурсивно вызывает сериализаторы подобъектов. локальности не получается
Здравствуйте, BulatZiganshin, Вы писали:
BZ>что же касается концепции монад, это это уже было обобщение этого паттерна, использование его в других областях. на данный момент можно сказать, что монады — это стратегия вычислений, определяемая отдельно от самих этих вычислений
Со всем согласен, кроме последнего утверждения. AFAIK, применять монады для формализации вычислений впервые предложил Moggi в статье: http://citeseer.ist.psu.edu/moggi89computational.html
И уже там говорится, что с помощью монад можно моделировать изменяемое состояние (а не ввод-вывод) и continuations.
Эта статья менее популярна, чем Imperative functional programming (последняя на работу Moggi ссылается), т.к. читателя в ней не жалеют, грузят theoretical computer science по полной программе.
Здравствуйте, palm mute, Вы писали:
PM>Здравствуйте, BulatZiganshin, Вы писали:
BZ>>что же касается концепции монад, это это уже было обобщение этого паттерна, использование его в других областях. на данный момент можно сказать, что монады — это стратегия вычислений, определяемая отдельно от самих этих вычислений
PM>Со всем согласен, кроме последнего утверждения. AFAIK, применять монады для формализации вычислений впервые предложил Moggi в статье: PM>http://citeseer.ist.psu.edu/moggi89computational.html PM>И уже там говорится, что с помощью монад можно моделировать изменяемое состояние (а не ввод-вывод) и continuations.
PM>Эта статья менее популярна, чем Imperative functional programming (последняя на работу Moggi ссылается), т.к. читателя в ней не жалеют, грузят theoretical computer science по полной программе.
я сейчас подумал и решил, что ошибся уникальные типы — это конкретная реализация IO монады, можно делать и по-другому (в hbc, где они кажется впервые и были реализованы, использовались continuations). так что монады — это вообще не способ *реализации* императивности. это способ описания её в рамках *чистого* языка. а реализовать затем эту >>= иожно и так, и эдак, и анверно ещё другие варианты можно придумать. так что монада — это спецификация поведения >>=, это контракт, а трюк с RealWorld — это реализация, удовлетворяющая этой спецификации
Здравствуйте, EvilChild, Вы писали:
VD>>Авторам этого языка к сожалению не удалось создать язык отвечающий этим требованиям. EC>Что именно из этого списка не удалось? Можешь аргументировать?
1. It should be suitable for teaching, research, and applications, including building large systems.
EC>>>Haskell и есть та экспериментальная площадка, на которой обкатываются идеи, которые попадают в мейнстрим. VD>>Ты внимательно читал то что я написал прежде чем отвечать? Или у тебя прицип в жизни такой отчечать все что угодно лиш бы оно не имело никакого отношения к словм оппонентов? EC>Давай ты оставишь в покое мои припницы. Почему ты вместо ответа на вопрос постоянно переходишь на личности?
Потому что некоторые личности постоянно передергивают, подменяют темы разговра, несут просто откровенную ахинею и на просьбу объяснить связь этой ахинеии с моими высказваниями задают вопрос вместо такго чтобы дать ответ.
Так же эти личности постоянно обрезают задаваемые им вопросы, не отвечая на них.
Так вот в этом случае меня лично просто раздражает странность и не связанность твои ответов. Нопомню еще раз сто я сказал: VD>>Я считаю, что пришло время перевести мэйнстрим на языки которые будут мало отличаться от сегодняшних фоваритов (С++, C# и Java) по эффективности, но при этом дадут возможность существенно поднять уровень разработки.
На что ты мне ответил: EC>Haskell и есть та экспериментальная площадка, на которой обкатываются идеи, которые попадают в мейнстрим.
Извини, но "Кащщено". Кто тебя спрашивал о "площадках"? Речь идет не о эксперементах, а о реальном применении. Причем тут "экспериментальная площадка"? В чем логика?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
VD>>Слова "query monad, как в HaskellDB, над которым, кстати, он работал" вообще каша какая-то.
L>Если ты чего то не понимаешь, это не значит, что этого нет. Определись, что именно тебе не понятно, спроси знающих людей, уверен, тебе ответят.
Ну, так ты потрудишся объяснить какое отношение монады имеют к C#? И где ты их узрел в LINQ?
Или то основание, что люди подглядели общую идею в Хаскеле где ее реализация была сделана через монады достаточно чтобы считать что в C# появились монады?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Если же под более легкими для понимания сущностями ты имеешь внесение в язык явного императива, то это мы с тобой уже обсуждали: это (минимум) вопросы целей, и цели авторов языка могут не совпадать с твоими.
Именно это я имею в виду. Так будет прямой ответ (да/нет)?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>>>Авторам этого языка к сожалению не удалось создать язык отвечающий этим требованиям. EC>>Что именно из этого списка не удалось? Можешь аргументировать? VD>
1. It should be suitable for teaching, research, and applications, including building large systems.
В некоторых европейских ВУЗах его используют как первый язык программирования при обучении.
Я правда не настаиваю, что Haskell идеальный язык для этого.
Но с остальными пунктами вроде всё в порядке, согласен?
Просто для несогласия с частью одного пункта из шести, твоё утверждение слишком сильное, не находишь?
Так, что по части передёргивания ты тоже грешен.
VD>Извини, но "Кащщено". Кто тебя спрашивал о "площадках"? Речь идет не о эксперементах, а о реальном применении. Причем тут "экспериментальная площадка"? В чем логика?
В данном конкретном случае соглашусь с тобой — малость невпопад ответил (загнался в полемическом пылу).
В общем давай будем обсуждать не недостатки друг друга (они мало кому кроме нас интересны), а языки программирования.
Здравствуйте, VladD2, Вы писали:
VD>Ну, так ты потрудишся объяснить какое отношение монады имеют к C#? И где ты их узрел в LINQ?
Почему опять трудится должен я? Потрудись перечитать мой ответ. Что тебе в нём непонятно?
VD>Или то основание, что люди подглядели общую идею в Хаскеле где ее реализация была сделана через монады достаточно чтобы считать что в C# появились монады?
Здравствуйте, VladD2, Вы писали:
VD>Именно это я имею в виду. Так будет прямой ответ (да/нет)?
Да (в смысле, прямой ответ — да). Твоё решение, например, более легкое для твоего понимания. Это что нибудь меняет? Легкость в, повторю, первоначальном понимании по твоему является наиважнейшим и единственным фактором при выборе решения?
-- трививальная монада Identity
-- M a идентично atype M a = a
-- returnM a идентично a
returnM a = a
-- bindM a f идентично f a
bindM a f = f a
showM a = showVal a
-- Если заменить в коде интерпертатора все функции *M и конструкторы типа M * на их значение, то функция
-- interprete упростится до следующей (слабо отличающейся от реализации на Nemele, которую приводил Влад)
-- interprete :: Term -> Environment -> Value
-- interprete (Var x) e = searchFor x e
-- interprete (Constant i) e = Num i
-- interprete (Add x y) e = add (interprete x e) (interprete y e)
-- interprete (Apply f a) e = apply (interprete f e) (interprete a e)
-- interprete (Lambda x v) e = Fun (\a -> interprete v ((x,a):e))
-- Вычислив test term0 в интерпретаторе Хаскела получим ожидаемый результат "42"
-- Main> test term0
--"42"
--Main> test term1
--"function"
--Main> test (Apply (Constant 1) (Constant 2))
--"<wrong>"
-- основной код интерпретатора остался без измененийtype Name = String
data Term = Var Name
| Constant Int
| Add Term Term
| Lambda Name Term
| Apply Term Term
data Value = Wrong
| Num Int
| Fun (Value -> M Value)
type Environment = [(Name, Value)]
showVal :: Value -> String
showVal Wrong = "<wrong>"
showVal (Num i) = show i
showVal (Fun f) = "function"
interprete :: Term -> Environment -> M Value
interprete (Var x) environment = searchFor x environment
interprete (Constant i) environment = returnM (Num i)
interprete (Add x y) environment = bindM x_value
(\a ->
bindM y_value
(\b -> add a b))
where
x_value = (interprete x environment)
y_value = (interprete y environment)
interprete (Apply function argument) environment = bindM function_value
(\a ->
bindM argument_value
(\b -> apply a b))
where
function_value = (interprete function environment)
argument_value = (interprete argument environment)
interprete (Lambda x v) environment = returnM (Fun (\a -> interprete v ((x,a) : environment)))
searchFor :: Name -> Environment -> M Value
searchFor x [] = returnM Wrong
searchFor x ((y,b) : environment) = if x ==y
then returnM b
else searchFor x environment
add :: Value -> Value -> M Value
add (Num x) (Num y) = returnM (Num (x+y))
add x y = returnM Wrong
apply :: Value -> Value -> M Value
apply (Fun function) argument = function argument
apply function argument = returnM Wrong
test :: Term -> String
test term = showM (interprete term [])
term0 = (Apply (Lambda "x" (Add (Var "x") (Var "x")))
(Add (Constant 10) (Constant 11)))
term1 = (Lambda "x" (Add (Var "x") (Var "x")))
-- добавим вывод ошибок в наш интерпретатор
-- значение может быть либо успешным либо ошибкойdata M a = Success a | Error String
returnM a = Success a
-- определяем bindM для успешной и ошибочной ситуации
bindM (Success a) f = f a
bindM (Error s) f = Error s
-- определяем showM аналогично bindM
showM (Success a) = "Success : " ++ showVal a
showM (Error s) = "Error : " ++ s
-- добавляем новую функцию в нашу монаду - errorM
errorM s = Error s
-- и заменяем все вхождения "returnM Wrong" на соответствующий вызов "errorM"
-- таких мест не много
-- searchFor x [] = returnM Wrong
-- add x y = returnM Wrong
-- apply function argument = returnM Wrong
-- эти функции будут выглядеть следующим образом
-- searchFor x [] = errorM("unbound variable: " ++ x)
-- add x y = errorM("should be numbers : " ++ showVal x ++ "," ++ showVal y)
-- apply function argument = errorM("should be a function : " ++ showVal function
-- и результат выполнения проверок
--Main> test term0
--"Success : 42"
--Main> test term1
--"Success : function"
--Main> test (Apply (Constant 1) (Constant 2))
--"Error : should be a function : 1"
-- Как утверждает Вадлер,
-- без использования монад,
-- возможный вариант обработки ошибок был бы выброс исключений
-- или continuation passingtype Name = String
data Term = Var Name
| Constant Int
| Add Term Term
| Lambda Name Term
| Apply Term Term
data Value = Wrong
| Num Int
| Fun (Value -> M Value)
type Environment = [(Name, Value)]
showVal :: Value -> String
showVal Wrong = "<wrong>"
showVal (Num i) = show i
showVal (Fun f) = "function"
interprete :: Term -> Environment -> M Value
interprete (Var x) environment = searchFor x environment
interprete (Constant i) environment = returnM (Num i)
interprete (Add x y) environment = bindM x_value
(\a ->
bindM y_value
(\b -> add a b))
where
x_value = (interprete x environment)
y_value = (interprete y environment)
interprete (Apply function argument) environment = bindM function_value
(\a ->
bindM argument_value
(\b -> apply a b))
where
function_value = (interprete function environment)
argument_value = (interprete argument environment)
interprete (Lambda x v) environment = returnM (Fun (\a -> interprete v ((x,a) : environment)))
searchFor :: Name -> Environment -> M Value
searchFor x [] = errorM("unbound variable: " ++ x)
searchFor x ((y,b) : environment) = if x ==y
then returnM b
else searchFor x environment
add :: Value -> Value -> M Value
add (Num x) (Num y) = returnM (Num (x+y))
add x y = errorM("should be numbers : " ++ showVal x ++ "," ++ showVal y)
apply :: Value -> Value -> M Value
apply (Fun function) argument = function argument
apply function argument = errorM("should be a function : " ++ showVal function)
test :: Term -> String
test term = showM (interprete term [])
term0 = (Apply (Lambda "x" (Add (Var "x") (Var "x")))
(Add (Constant 10) (Constant 11)))
term1 = (Lambda "x" (Add (Var "x") (Var "x")))
-- Добавим к выводу ошибок еще и позицию в которой ошибка была найдена.
--Пусть Position будет типом, который будет определять позицию ошибки в тексте
-- допустим, номер линии
-- Расширим тим данных Term дополнительным конструктором,
-- который будет определять позицию
-- data Term = ... | At Position Term
-- например конструкция (At p (Apply t (At q u))) означает, что
-- p это позиция терма (Apply t (At q u))
-- q это позиция части терма u
-- для удобства определения позиции создадим новый тип
-- теперь позицию можно будет определять как
-- (Apply (Constant 0) (At (Pos 4) (Var "x")))
-- терм (Var "x") будет находится на позиции 4data Position = Pos Int--Переопределяем функцию show, чтобы была возможность выводить позицию на экранinstance Show Position where
show (Pos i) = show i
-- Мы определим новую монаду , которая принимает в качестве параметра позицию,
-- которая используется при выведении ошибкиtype M a = Position -> E a
-- игногируем позицию
returnM a = \p -> returnE a
-- добавляем позицию в строку сообщения об ошибке
errorM s = \p -> errorE (show p ++ ": " ++ s)
-- передаем позицию в агрумент и функцию
-- `bindE` - инфиксаня форма bindE
bindM m k = \p -> m p `bindE` (\x -> k x p)
-- позиция по умолчанию - 0
showM m = showE (m pos0)
pos0 = Pos 0
-- эта функция используется для изменения позиции.
-- она получает на вход новую позицию и монадическое значение старой позиции
-- и возвращает новое значение позиции завернутое в монаду
resetP :: Position -> M x -> M x
resetP q m = \p -> m q
-- использовавшуюся в предыдущем примере монаду преименовываем в E
-- и точно таким же образом переименовываем все ее методы.data E a = Success a | Error String
returnE a = Success a
bindE (Success a) f = f a
bindE (Error s) f = Error s
showE (Success a) = "Success : " ++ showVal a
showE (Error s) = "Error : " ++ s
errorE s = Error s
-- осталось совсем чуть чуть. сделать так, чтобы интерпретатор мог обрабатывать At термы
-- в функцию interprete добавляем следующую строку
-- interprete (At p t) e = resetP p (interprete t e)
-- она будет менять значение позиции на каждом терме At
-- Больше никаких изменений не требуется.
--То есть все изменения(не учитываем добавленный код) свелись к переименовыванию конструктора типа монады E и ее методов
-- Далее слово Вадлеру (переводить совсем уж лениво)
-- Without monads, or a similar technique, this modification would be far more tedious.
-- Each clause of the interpreter would be need to rewritten
-- to accept the current position as an additional parameter,
-- and to pass it on as appropriate parameter at each recursive call
-- In an impure language , this modification is not quite so easy.
-- One method is to use a state variable that contains a stack of positions
-- Care must be taken to maintain the state property : push a position onto the stack
-- and pop a position off the stack when leaving it.
-- Ну и тестовый пример для запуска в интерпретаторе Хаскела
--Main> test (Apply (Constant 0) (At (Pos 4) (Var "x")))
--"Error : 4: unbound variable: x"type Name = String
data Term = Var Name
| Constant Int
| Add Term Term
| Lambda Name Term
| Apply Term Term
| At Position Term
data Value = Wrong
| Num Int
| Fun (Value -> M Value)
type Environment = [(Name, Value)]
showVal :: Value -> String
showVal Wrong = "<wrong>"
showVal (Num i) = show i
showVal (Fun f) = "function"
interprete :: Term -> Environment -> M Value
interprete (Var x) environment = searchFor x environment
interprete (Constant i) environment = returnM (Num i)
interprete (Add x y) environment = bindM x_value
(\a ->
bindM y_value
(\b -> add a b))
where
x_value = (interprete x environment)
y_value = (interprete y environment)
interprete (Apply function argument) environment = bindM function_value
(\a ->
bindM argument_value
(\b -> apply a b))
where
function_value = (interprete function environment)
argument_value = (interprete argument environment)
interprete (Lambda x v) environment = returnM (Fun (\a -> interprete v ((x,a) : environment)))
interprete (At p t) e = resetP p (interprete t e)
searchFor :: Name -> Environment -> M Value
searchFor x [] = errorM("unbound variable: " ++ x)
searchFor x ((y,b) : environment) = if x ==y
then returnM b
else searchFor x environment
add :: Value -> Value -> M Value
add (Num x) (Num y) = returnM (Num (x+y))
add x y = errorM("should be numbers : " ++ showVal x ++ "," ++ showVal y)
apply :: Value -> Value -> M Value
apply (Fun function) argument = function argument
apply function argument = errorM("should be a function : " ++ showVal function)
test :: Term -> String
test term = showM (interprete term [])
term0 = (Apply (Lambda "x" (Add (Var "x") (Var "x")))
(Add (Constant 10) (Constant 11)))
term1 = (Lambda "x" (Add (Var "x") (Var "x")))
Здравствуйте, lomeo, Вы писали:
L>Почему опять трудится должен я?
Потому что ты вступился за бездакозательное заявление.
L>Потрудись перечитать мой ответ. Что тебе в нём непонятно?
В нем нет ответа на мои вопросы. В частности я просил показать монады в C# и объяснить зачем они вообще нужны в этом фзыке.
VD>>Или то основание, что люди подглядели общую идею в Хаскеле где ее реализация была сделана через монады достаточно чтобы считать что в C# появились монады?
L>Нет, конечно, при чём тут вообще это?
При том что единственная разумная мысль в ваших с ИвелЧилдом рассуждениях была ссылка на фразу о том, что идея LINQ навеяна квэри-компрехеншоном из Хаскеля.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Ты меня извини, но у меня даже нет времени как следует разбираться с приведенным тобой кодо. Да и желания тоже нет, так как код испишрен однобуквенными идентификаторами до смысла которых нужно догадваться. Продираться сквозь эту криптографию к тому же в плохо знакомом мне языке, да еще и смачно смазанном этими самыми монадами я не рескну, даже при наличии коменатриев.
Темболее мне не хочется писать пдобную груду кода.
Прицитпиальных проблем повторить пдобную фигню на Немерле я не вижу. Если ты видишь здесь проблемы, то будь добр выдели их в коротком примере и опиши как следует, а я тогда объясню как я тоже самое сделаю без монад на Немерле. ОК?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
VD>>Именно это я имею в виду. Так будет прямой ответ (да/нет)?
L>Да (в смысле, прямой ответ — да).
Этого достаточно. Далее остается применить прицип Оккама.
L> Твоё решение, например, более легкое для твоего понимания. Это что нибудь меняет?
Естественно. Я не фанат функциональщик который будет делать вид, что все очевидно там где все запутанно. Таких как ты найдутся еденицы, такик как я подавляющее больинство. Именно от того ФЯ и сидят в заднице. Они делались людми с мягко говоря сильно отличающейстя психикой.
L> Легкость в, повторю, первоначальном понимании по твоему является наиважнейшим и единственным фактором при выборе решения?
При выборе языка. При принятии решения возиться с ним или бросить. Да и вообще при принятии решений. Из двух решений всегда надо выбрить более простой и понятное если коенчнь оно подходит. Тут я с тов. Оккамом совершенно согласен.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Как программист пишет код — хоть на голове, это его личное дело. А вот результат ничем не будет отличаться от императивного кода на другом языке. КАК это представлено внутри — без разницы. Поскольку realworld реально не используется — мы получим обычное последовательное (читай императивное) исполнение кода безо всяких realworld.
Разница огромна. Разница в том, что булшит с realworld из серии "это нужно запомнить" и поймут такие решения (точнее даже заходят понимать) далеко не все (точнее мало кто).
L>Что тебя смущает, не пойму? Выглядит код как императивный, компилируется и работает как императивный, что ещё надо то?
VD>>Если бы такое "уменьшение" было бы благом, то в Хаскеле даже числа были бы перечислениями объявленными в каком-нить модуле.
L>Не придумывай. Дело не в том, что уменьшение не благо, а в том, что это просто невозможно. Во всём остальном числа (целые) ведут себя как обычные перечисления.
От, блин, а мужики то и не знали. Арабы хрен знает сколько лет назад придумали позиционную систему счисления и пользуются ее. Описываенся она на раз. А у Хаскеля идеологические проблемы. Впроче, как всегда. Вот по этому я и говорию, что это интеллектуальное извращение и самообман. Попытка отгородиться от окружающего мира шорами.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Mirrorer, Вы писали:
VD> Да и желания тоже нет, так как код испишрен однобуквенными идентификаторами до смысла которых нужно догадваться.
Это у Вадлера он в однобуквенных идентификаторах. Я старался избавиться от них, оставляль только в очевидных случаях типа Add x y
VD>Темболее мне не хочется писать пдобную груду кода.
Там больше комментариев чем кода.
VD>Прицитпиальных проблем повторить пдобную фигню на Немерле я не вижу.
Дык их и нету. Причем можно повтороить 1 в 1 буквально. Что я наверное сделаю как будет время.
VD>Если ты видишь здесь проблемы, то будь добр выдели их в коротком примере и опиши как следует, а я тогда объясню как я тоже самое сделаю без монад на Немерле. ОК?
Ок. Давай кратко опишу задачу. Простейший интерпретатор с грамматикой
-- Имена переменных описываются строкойtype Name = String-- Термом может быть
-- Переменнаяdata Term = Var Name
-- Константа
| Constant Int-- Операция сложения
| Add Term Term
-- Лямбда
| Lambda Name Term
-- Операция вычисления
| Apply Term Term
-- Значением может быть
-- Ошибкаdata Value = Wrong
-- Число
| Num Int-- Функция (Functions are first class values :super:)
| Fun (Value -> M Value)
К нему необходимо добавить
на первом этапе банальную интерпретацию.
на втором этапе обработку ошибок (просто говорить unbound variable или там should be numbers если в операцию сложения передается что-то отличное от чисел)
на третьем этапе добавить локализацию ошибки. То есть показывать позицию в которой ошибка произошла.
На каждом этапе указать что и сколько нужно поменять в коде.
Вроде все.
"Если Вы отличаетесь от меня, то это ничуть мне не вредит — Вы делаете меня богаче". Экзюпери
Здравствуйте, Vermicious Knid, Вы писали:
VK>// имхо незачем замусоривать ast локациями, пусть они будут отдельно
Вот тут кстати +1 Пока ехал на работу, подумал о том, что введение локаций в AST это больше хак к монадам имеющий слабое отношение.
VK>Теперь пример с использованием исключений и без лишней функциональности, полученный из вышепревиденного примера:
Красиво и аккуратно.
"Если Вы отличаетесь от меня, то это ничуть мне не вредит — Вы делаете меня богаче". Экзюпери
Здравствуйте, VladD2, Вы писали:
L>>Почему опять трудится должен я?
VD>Потому что ты вступился за бездакозательное заявление.
Перечитай мой первый пост. Я указал тебе на то, что ты путаешь IO-монаду и монаду вообще. Сколько раз я должен это повторить, чтобы ты понял, что эмуляция императива IO монады никаким боком не лежит к query монаде?
L>>Потрудись перечитать мой ответ. Что тебе в нём непонятно?
VD>В нем нет ответа на мои вопросы. В частности я просил показать монады в C# и объяснить зачем они вообще нужны в этом фзыке.
Это неправда. Я тебе и показал и объяснил. Объяснил, правда, в другом посте. Если тебя это не устраивает, то ещё раз прошу тебя показать, что ИМЕННО в моём ответе тебя не устраивает. Спор получается в стиле
— покажи где?
— вот, например.
— нет ты покажи где.
VD>>>Или то основание, что люди подглядели общую идею в Хаскеле где ее реализация была сделана через монады достаточно чтобы считать что в C# появились монады?
VD>При том что единственная разумная мысль в ваших с ИвелЧилдом рассуждениях была ссылка на фразу о том, что идея LINQ навеяна квэри-компрехеншоном из Хаскеля.
Здравствуйте, VladD2, Вы писали:
L>>Да (в смысле, прямой ответ — да).
VD>Этого достаточно. Далее остается применить прицип Оккама.
При прочих равных — согласен.
L>> Твоё решение, например, более легкое для твоего понимания. Это что нибудь меняет?
VD>Естественно. Я не фанат функциональщик который будет делать вид, что все очевидно там где все запутанно.
Путаешься в монадах? Не используй Хаскель, проблем то.
VD> Таких как ты найдутся еденицы, такик как я подавляющее больинство.
Спасибо. Для меня это комплимент.
VD>Именно от того ФЯ и сидят в заднице. Они делались людми с мягко говоря сильно отличающейстя психикой.
У кого как. У меня вот ФЯ в голове сидят. А насчёт психики — ну да, человек должен отличаться, чтобы увидеть что то неувиденное другими. Это же хорошо.
L>> Легкость в, повторю, первоначальном понимании по твоему является наиважнейшим и единственным фактором при выборе решения?
VD>При выборе языка. При принятии решения возиться с ним или бросить. Да и вообще при принятии решений. Из двух решений всегда надо выбрить более простой и понятное если коенчнь оно подходит. Тут я с тов. Оккамом совершенно согласен.
Нет. Из двух решений всегда надо выбирать подходящее. Подходящее для достижения цели. Простота и понятность — это немаловажные, но частности. Они учитываются при определении — подходит ли решение для достижения цели и насколько хорошо, но не являются определяющими.
Если для тебя это по другому — ну что ж? Может твоя цель — достижение простоты и понятности
Здравствуйте, VladD2, Вы писали:
VD>Разница огромна. Разница в том, что булшит с realworld из серии "это нужно запомнить" и поймут такие решения (точнее даже заходят понимать) далеко не все (точнее мало кто).
Да не нужно этого запоминать. Даже знать то об этом не нужно. Другое дело, что те, кто пишет — хочет знать. Такие уж они люди — любопытные. Если они не понимают — они спрашивают.
L>>Что тебя смущает, не пойму? Выглядит код как императивный, компилируется и работает как императивный, что ещё надо то?
Ответишь на этот вопрос? Может разберёмся, что именно тебе не понятно.
L>>Не придумывай. Дело не в том, что уменьшение не благо, а в том, что это просто невозможно. Во всём остальном числа (целые) ведут себя как обычные перечисления.
VD>От, блин, а мужики то и не знали. Арабы хрен знает сколько лет назад придумали позиционную систему счисления и пользуются ее. Описываенся она на раз. А у Хаскеля идеологические проблемы. Впроче, как всегда. Вот по этому я и говорию, что это интеллектуальное извращение и самообман. Попытка отгородиться от окружающего мира шорами.
И? Каким образом позиционная система счисления позволяет нам записывать перечисление?
Здравствуйте, lomeo, Вы писали:
L>Вот и всё. От монад мы легко пришли к LINQ — я показал, что у них есть общего?
А почему бы не через continuations? Можно доказать то же самое — но без термина монада.
Здравствуйте, GlebZ, Вы писали:
GZ>А почему бы не через continuations? Можно доказать то же самое — но без термина монада.
continuations выражаются через монады .
GlebZ,
GZ>Если отказаться от догмата — то нужно отказаться от этого будущего. GZ>А монады — непротиворечат pure. Они лишь вводят новый закон нетранзитивности.
А что за закон такой? Ты наверное хотел сказать "вводят отношение частичного порядка"?
Здравствуйте, palm mute, Вы писали:
PM>continuations выражаются через монады .
Насколько я понял(возможно ошибочно) из статьи Вадлера обратное тоже справедливо
"Если Вы отличаетесь от меня, то это ничуть мне не вредит — Вы делаете меня богаче". Экзюпери
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>А что за закон такой? Ты наверное хотел сказать "вводят отношение частичного порядка"?
Возможно. Я в математике монад не большой дока. Просто пришло на ум из другой области, если множество (а можно сказать и функции) нетранзитивно, то трансформировать(менять местами) их нельзя. Частичный порядок — несколько другая вещь. Если есть, можешь дать ссылку на описание мат. основы монад?
Здравствуйте, BulatZiganshin, Вы писали:
BZ>как я понимаю, композиция этих extension methods в haskelдВи делалась как раз с помощтю монады.
Не правльно понимаешь. В Хаскель нет понятия объектов. В нем все фукнции являются глобальными. Так что аналогов в нем просто нет. Методы-расширения это всего лишь возможность вызвать статически метод не так:
int x = SomeClass.SomeStaticMethod(someObject, "a");
а так:
int x = someObject.SomeStaticMethod(1, "a");
В Хаскеле пожалуй прямым аналого будет оператор piplene — |>.
BZ> что давало возможность писать императвиный код внутри этого как бы sql-запроса.
Оставь свои домысли. В C# функциональный код писать не просто. А императивный можно писать везде и всегда.
BZ> можежь сравнить это с List monad — она перечисляет все значения в списке и позволет тебе выполнить какие-то вычисления над ними, или отфильтровать их
Это вообще не в кассу. В C# почти все встроенные коллекции позволяют модификацию по месту. Это вообще не проблема. Линк же использует идею итераторов. Собственно итераторы ты уже мог наблюдать здесь
Здравствуйте, lomeo, Вы писали:
L>Я показывал общие свойства.
Ничего ты не показал.
L>Допустим, мы разрабатываем конкретную монаду в C#. Ну, предположим, у нас есть время поизвращаться. Дальше код условный, я на С# не пишу.
Вот с этого надо и начинать было. "С# и занимаюсь гипотетическими рассуждениями...".
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Sinclair, Вы писали:
S>Может быть, аналог такого тоже можно изобразить в виде монады на функциональном языке. Но это уже скорее из области доказательства взаимной эквивалентности машины Тьюринга и частично-рекурсивных функций.
Вот именно. Плюс демагогия разводимая на базе этого факта.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Но ведь каждый думает по своему, когда решает какую то задачу. Монада — это паттерн, решающий задачу. Допустим, мы идём от него — мы же хотим выяснить связь?
Блин, для особо упертых... Да, паттерн, но паттерн Хаскеля. В ООЯ ему просто нет места. Конечно его даже можно изобразить на ООЯ в которых поддерживаются функциональные объекты, но вот нужны в нем нет, так как есть другие подходы более естесвне6нные для этих языков.
ЗЫ
Так нам будут показаны куски LINQ в которых используются монады?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, palm mute, Вы писали:
PM>Здравствуйте, GlebZ, Вы писали:
GZ>>А почему бы не через continuations? Можно доказать то же самое — но без термина монада. PM>continuations выражаются через монады .
ОК, господа трепачи. Вот вам C#. Монады вы на нем сотворите без проблем, это вы уже тут раз дващцать сказали. Тогда пользуясь истенностью вашего послендего утверждения "continuations выражаются через монады" и реализуйте, плиз, в C# continuations. Лично скажу вам огромное спасибо и поклонись до земли. Ну, а если кода не будет, то будем считать это силивом по полной порогрмме на чем и закончим эту дисскуссию.
ОК?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
...
По-моему, зачательная демонстрация того, что простые и прямые решения лучше чем эмуляция. И не важно ради чего эта эмуляци делается, из соображений совместимости, или в пылу борьбы за чистоту.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mirrorer, Вы писали:
VK>>Теперь пример с использованием исключений и без лишней функциональности, полученный из вышепревиденного примера: M>Красиво и аккуратно.
Но менее фунционально. Ведь пример с исключениями останавливается на превой ошибке. В реальных компиляторах так поступать нельзя.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mirrorer, Вы писали:
M> Это у Вадлера он в однобуквенных идентификаторах. Я старался избавиться от них, оставляль только в очевидных случаях типа Add x y
К сожалению не всегда все очевидно m, a, s и т.п. просто сбивают с толка.
VD>>Темболее мне не хочется писать пдобную груду кода. M>Там больше комментариев чем кода.
И все же. У меня еще дел полно, а пенисометрия заранее бессмысленная.
Открою секрет, я обычно пишу пенисометрический код только если он нужен мне где-то еще. Например, в статье. Получается чтл-то вроде продукции двойного назнанчения.
VD>>Прицитпиальных проблем повторить пдобную фигню на Немерле я не вижу. M>Дык их и нету. Причем можно повтороить 1 в 1 буквально. Что я наверное сделаю как будет время.
Имеется в виду без монад. Они здесь лишнии. Это костыли Хаскеля для бопрьбы с отуствием сотсояния и ленивостью.
M>Ок. Давай кратко опишу задачу. Простейший интерпретатор с грамматикой
...
Блин, я хринею. Взял и практически повторил свой исходный пример. на "простейший интерпретатор" это мало похоже. Простейший я уже приводил. Плюс в исходниках Немела есть "сложнеший", т.е. интерпретатор самого Немерла.
Ты бы лучше выделял задачу которую хочешь продемонстрировать на минимальном примере, а не на "простейшем" в твоем понимании. Темболее что Vermicious Knid уже реализовал твой пример. Жаль, что только толку для окружающих в этом всем мало. Ведь конретных проблем вы так и не продемонстировали. А без этого для 99% читателей ваших соощений все это куча закорючек.
Хотя конечно визуально видно, что код на Хаскеле как минимум не короче, и точно более запутан и менее понятен. Что лично меня только укрепляет во мнении, что монады в импертивных языках не нужны, а Хаскелю они нужны как костыли позволющие обхдить чрезмерную чистоту.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Путаешься в монадах? Не используй Хаскель, проблем то.
Я не то что бы путась. Я нелюблю когда трехэтажные навороты применяются на ровном месте. Опять же тот же принцип Оккама. Хороший надо признать принцип, хотя и эмпирический.
Хаскель я тоже не применяю, так как мне не интересны задаче в которых не важна скорость. Незнаю почему. Не српашивай. Просто так выходит, что все чем бы мне не было интересно заниматься требует максимальной производительности для приемлемой работы на современной технике.
VD>> Таких как ты найдутся еденицы, такик как я подавляющее больинство.
L>Спасибо. Для меня это комплимент.
Пожалуйста. Годрись этим. Но практической пользы от этого — 0.
VD>>При выборе языка. При принятии решения возиться с ним или бросить. Да и вообще при принятии решений. Из двух решений всегда надо выбрить более простой и понятное если коенчнь оно подходит. Тут я с тов. Оккамом совершенно согласен.
L>Нет. Из двух решений всегда надо выбирать подходящее.
Так. Извини, но мне надоело принимать в бесполезной словесной переплаке. Ты встал в ряд демагогов. Если будет сказть что-то интересное, то я с удовольствием выслушаю. А смотреть на словесную эквилибристику и контр-аргументацию в стиле "нет не белое, а белое" не не интересно.
Адью.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
VD>>От, блин, а мужики то и не знали. Арабы хрен знает сколько лет назад придумали позиционную систему счисления и пользуются ее. Описываенся она на раз. А у Хаскеля идеологические проблемы. Впроче, как всегда. Вот по этому я и говорию, что это интеллектуальное извращение и самообман. Попытка отгородиться от окружающего мира шорами.
L>И? Каким образом позиционная система счисления позволяет нам записывать перечисление?
Какой бред, а?! Какие перечисления? Перечисление конечно по определению. А числа бесконечны. Это в Хаскеле было принято идиотское решение считать числа перечислением. Вот пусть и решают сами же созданные проблемы. А я лучше у арабов поучусь. Пишу 1 получаю "один". Пишу 1 и еще 1, т.е. 11, получаю "один десяток и один" или "одинащцать". И никаких идеологических проблем.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, GlebZ, Вы писали:
GZ>Влад. Для начала нужно понять что такое догмат "чистоты" в особенности со стороны компилятора. Это не Lazy. Lazy — всего лишь одна из оптимизаций.
Ты мня извини, но прежде чем кидаться что-то объяснять можно спросить у того кому собрался объяснять, а "не знает ли он этого?". Так вот отвечу — знаю. Но ленивость и чистота в Хаскеле ваимозависимые вещи. Желание сделать весь код линивым вынуждает делать его чистым, а полная чистота требует ленивости. Монады же призваны обходить оба ограничения делая вычисления последовательными и модифицирующими в казалось бы чисто-фукнциональном языке. Другими словами они эмулируют то что в других языках есть штатно: императивность и объектную ориентацию.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Перечитай мой первый пост. Я указал тебе на то, что ты путаешь IO-монаду и монаду вообще.
Суть от этого не меняется. Утверждение "монады нужны хаскелю для обхода сосбвенной чистоаты и ленивости" не становится не верным. И утверждение "в ООЯ применение монад бессмысленно" тоже.
В общем, так как показать необходимость монад в ООЯ вы не в силах вопрос читаю ичепраным.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Суть от этого не меняется. Утверждение "монады нужны хаскелю для обхода сосбвенной чистоаты и ленивости" не становится не верным. И утверждение "в ООЯ применение монад бессмысленно" тоже.
Последнее, очевидно, ложно. Если я применяю монады в ООЯ, то это имеет определенный смысл.
VD>В общем, так как показать необходимость монад в ООЯ вы не в силах вопрос читаю ичепраным.
Необходимость монад даже в ФЯ показывать никто и не предлагал.
Здравствуйте, VladD2, Вы писали:
VD>Какой бред, а?! Какие перечисления? Перечисление конечно по определению.
Если бы такое "уменьшение" было бы благом, то в Хаскеле даже числа были бы перечислениями объявленными в каком-нить модуле
VD>А числа бесконечны. Это в Хаскеле было принято идиотское решение считать числа перечислением. Вот пусть и решают сами же созданные проблемы. А я лучше у арабов поучусь. Пишу 1 получаю "один". Пишу 1 и еще 1, т.е. 11, получаю "один десяток и один" или "одинащцать". И никаких идеологических проблем.
Не поверишь, в Хаскеле тоже так можно. И тоже никаких идеологических проблем!
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>GlebZ,
GZ>>Если есть, можешь дать ссылку на описание мат. основы монад?
LCR>Lomeo садист LCR>Хотя может быть у тебя пойдёт лучше чем у меня. LCR>На всякий случай прими во внимание ещё пункт 6 в этом списке
Здравствуйте, VladD2, Вы писали:
VD>Но менее фунционально. Ведь пример с исключениями останавливается на превой ошибке.
Монадный вариант тоже вываливается на первой ошибке. Так что функцонал тот же.
Здравствуйте, VladD2, Вы писали:
VD>К сожалению не всегда все очевидно m, a, s и т.п. просто сбивают с толка.
Эх.. Да, жаль сообщения редактировать нельзя.. Подправил бы. Но в целом не так уж важно.
VD> Что лично меня только укрепляет во мнении, что монады в импертивных языках не нужны,
Для меня это пока еще не совсем очевидно. Я еще планирую поиграться с монадой List, ходят слухи что с ее помощью можно довольно просто организовать list comprehension. Поглядим что из этого получится... Вполне может быть, что получится что-то страшное и неудобоваримое, но так чешутся руки попробовать...
Здравствуйте, lomeo, Вы писали:
VD>>Суть от этого не меняется. Утверждение "монады нужны хаскелю для обхода сосбвенной чистоаты и ленивости" не становится не верным. И утверждение "в ООЯ применение монад бессмысленно" тоже.
L>Последнее, очевидно, ложно. Если я применяю монады в ООЯ, то это имеет определенный смысл.
А ты применяещь монады в ООЯ? Нет? Значит очевидно нечто другое.
VD>>В общем, так как показать необходимость монад в ООЯ вы не в силах вопрос читаю ичепраным.
L>Необходимость монад даже в ФЯ показывать никто и не предлагал.
В ФЯ это никого не колышит. Ты покажи зачем они в ООЯ. Про не предлагал — это очевидная лож.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mirrorer, Вы писали:
M>Для меня это пока еще не совсем очевидно. Я еще планирую поиграться с монадой List, ходят слухи что с ее помощью можно довольно просто организовать list comprehension.
Ходят слухи, что у Камила Скальски реализация list comprehension на макросах заняла окло одного дня. И так же есть предположение, что никакие выверты не позволят расшириь C# подобной фичей без измененения компилятора.
M>Поглядим что из этого получится... Вполне может быть, что получится что-то страшное и неудобоваримое, но так чешутся руки попробовать...
Любиш ужастики?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Ходят слухи, что у Камила Скальски реализация list comprehension на макросах заняла окло одного дня. VD>И так же есть предположение, что никакие выверты не позволят расшириь C# подобной фичей без измененения компилятора.
Стоп. Ты сам мне объяснял почему немерлавцам пришлось для реализации list comprehension залезть в компилятор. Попросю быть объективным.
Здравствуйте, VladD2, Вы писали:
L>>А зачем вам монады в шарпе?
VD>Я плякаль.
Нет, ну на самом деле. Вспомни начало — ты сказал, что монады нужны для реализации императивности, поэтому они в шарпе не нужны (рассматривая LINQ). Я всего лишь указал, что эта частная монада, о которой ты рассуждаешь, нужна для реализации императивности. Поэтому твой вывод (в значении "выведение результата") неверен. Независимо от верности/неверности самого вывода (в значении "сам результат").
Я всего лишь сказал, что из того, что конкретные монады IO/State эмулируют императивность НЕЛЬЗЯ сделать вывод, что и все остальные монады не нужны в императивном языке. Для такого вывода нужны другие посылки. Всё.
Относительно того, монады нужны или не нужны — мне это неинтересно. И не смотря на это я понаприводил кучу примеров их возможного использования — ну вы же спрашиваете, может не знаете чего. В ответ получал только рекурсивное — а зачем они нужны? Зачем мне это приписывают, я не понимаю. Ну, разве что, чтобы не обсуждать то, с чем я действительно спорил, нет?
Здравствуйте, lomeo, Вы писали:
L>Относительно того, монады нужны или не нужны — мне это неинтересно. И не смотря на это я понаприводил кучу примеров их возможного использования — ну вы же спрашиваете, может не знаете чего. В ответ получал только рекурсивное — а зачем они нужны?
Есть подозрение что народ хочет увидеть такое применение монад, которое даст преимущество по сравнению с традиционным подходом..
То есть без монад — гемморой. А вот с монадами..
"Если Вы отличаетесь от меня, то это ничуть мне не вредит — Вы делаете меня богаче". Экзюпери
Здравствуйте, Mirrorer, Вы писали:
M>Есть подозрение что народ хочет увидеть такое применение монад, которое даст преимущество по сравнению с традиционным подходом.. M>То есть без монад — гемморой. А вот с монадами..
Я их понимаю, это очень похвальное желание, но я то тут при чём?
Безгеморройного применения монад они не увидят — вот без паттернов код геморройней же не становится. Просто паттерны облегчают нам нахождения решения в типовых ситуациях, поскольку фиксируют их. То же самое и паттерн "монада".
M>Есть подозрение что народ хочет увидеть такое применение монад, которое даст преимущество по сравнению с традиционным подходом.. M>То есть без монад — гемморой. А вот с монадами..
Здравствуйте, GlebZ, Вы писали:
GZ>Стоп. Ты сам мне объяснял почему немерлавцам пришлось для реализации list comprehension залезть в компилятор. Попросю быть объективным.
Значит ты плохо слушал. Там используется $ который является очень перегруженным символом в Немерле. А сам list comprehension реализован в виде отдельного макроса.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, deniok, Вы писали:
D>Маленькая поправочка — в Хаскелле это не так.
...Таким же образом мы могли бы определить Int (целые фиксированного диапазона) и Integer:
data Int = -65532 | ... | -1 | 0 | 1 | ... | 65532 –- ещё псевдо-код
data Integer = ... -2 | -1 | 0 | 1 | 2 ...
где -65532 и 65532 – это максимальное и минимальное целое фиксированного диапазона в данной реализации. Тип Int представляет собой существенно более широкое перечисление, чем Char, однако по-прежнему конечное! В противоположность этому псевдо-код для типа Integer предназначен для описания бесконечного перечисления.
Думаешь вольность автора?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, deniok, Вы писали:
D>>Маленькая поправочка — в Хаскелле это не так.
VD>
...Таким же образом мы могли бы определить Int (целые фиксированного диапазона) и Integer:
VD>data Int = -65532 | ... | -1 | 0 | 1 | ... | 65532 –- ещё псевдо-код
VD>data Integer = ... -2 | -1 | 0 | 1 | 2 ...
VD>где -65532 и 65532 – это максимальное и минимальное целое фиксированного диапазона в данной реализации. Тип Int представляет собой существенно более широкое перечисление, чем Char, однако по-прежнему конечное! В противоположность этому псевдо-код для типа Integer предназначен для описания бесконечного перечисления.
VD>Думаешь вольность автора?
скорее демонстрация принципов работы "data". я такое и для паскаля видел
что касается встроенности в язык — то встроены только числовые литералы. остальное встроено в библиотеки и на дефиниции языка афаир никак не сказывается
Здравствуйте, VladD2, Вы писали:
VD>Значит ты плохо слушал. Там используется $ который является очень перегруженным символом в Немерле. А сам list comprehension реализован в виде отдельного макроса.
Однако факт остается фактом. Если средний пользователь захотел-бы реализовать list comprehension — то он бы этого не смог бы сделать. Так как нужно залезть в компилятор. Факт он такой, либо он есть, либо его нет. Нельзя быть чуть чуть беременным. Поэтому ты зря привел этот аргумент в пример.
Здравствуйте, GlebZ, Вы писали:
GZ>Фактически, это теоретическая возможность построения оптимизатора по сравнению с которым оптимизаторы императивных языков — дети неразумные. И собственно к этому все и движется. Только там слишком много NP задач. Во многом, это похоже на ситуацию с оптимизацией SQL.
AndrewVK wrote: > C>Поэтому надо хранить историю изменений и помечать к какой ревизии > C>относятся ответы. > Надо. Кто б еще этим занялся.
Так открыли бы исходники — народ бы подтянулся, ИМХО.
AndrewVK wrote: > C>Так открыли бы исходники — народ бы подтянулся, ИМХО. > Сомневаюсь
Ну так без исходников точно не потянутся.
Я бы лично немного помог родному RSDN. Просто я не вижу в чем такая
большая сложность в коде форума, в свое время я сам написал движок (на
С++ и CGI!), слегка подобный RSDN. Хотя может я чего-то и недооцениваю.
Здравствуйте, Cyberax, Вы писали:
C>Я бы лично немного помог родному RSDN.
На шарпе? Тогда этот вопрос можно решить индивидуально
C> Просто я не вижу в чем такая C>большая сложность в коде форума, в свое время я сам написал движок (на C>С++ и CGI!), слегка подобный RSDN. Хотя может я чего-то и недооцениваю.
Дело не в сложности, дело в необходимости потратить массу времени и усилий.
Здравствуйте, GlebZ, Вы писали:
GZ>Однако факт остается фактом. Если средний пользователь захотел-бы реализовать list comprehension — то он бы этого не смог бы сделать. Так как нужно залезть в компилятор. Факт он такой, либо он есть, либо его нет. Нельзя быть чуть чуть беременным. Поэтому ты зря привел этот аргумент в пример.
Не выдумывай. Вся реализация лежит в двух макросах. Все что делается в компиляторе — это разрешается неоднозначтьсть символа '$'. Если его заменить на любой друго, то проблем не будет. Сотсвбенно вот код: http://nemerle.org/svn/nemerle/trunk/macros/Util.n
public module ListComprehensionHelper
{
[Nemerle.Macros.Hygienic]
public ExpandRange (inrange : PExpr, acc : PExpr) : option [PExpr]
{
match (inrange) {
| <[ $pat in $[$first, $second .. $last] ]>
| <[ $pat in [$first, $second .. $last] ]> =>
Some (<[
mutable i = $first;
mutable delta = $second - i;
def last = $last;
mutable cond = if (delta < 0) i >= last else i <= last;
def pre_last = unchecked (last - delta);
when (delta < 0 && pre_last < last || delta > 0 && pre_last > last) // we overflowed
delta = -delta;
while (cond) {
def $pat = i;
if (delta < 0)
cond = i >= pre_last;
else
cond = i <= pre_last;
unchecked (i += delta);
$acc;
}
]>)
| <[ $pat in $[$first .. $last] ]>
| <[ $pat in [$first .. $last] ]> =>
Some (<[
mutable i = $first;
def last = $last;
mutable cond = i <= last;
mutable pre_last = last;
unchecked (pre_last--); // can't use (last - 1) since 1 might change/widen type
def overflowed = pre_last > last;
while (cond) {
def $pat = i;
if (overflowed)
cond = i >= pre_last;
else
cond = i <= pre_last;
unchecked (i++);
$acc;
}
]>)
| _ => None ()
}
}
}
macro ExpandListComprehension (params exprs : list [PExpr])
{
def adder =
<[
def cell = $(exprs.Head) :: [];
if (head == null) {
head = cell;
tail = cell;
} else {
_N_skip_write_check (tail.tl) = cell;
tail = cell;
}
]>;
def loops =
exprs.Tail.Rev ().FoldLeft (adder,
fun (e, acc) {
match (ListComprehensionHelper.ExpandRange (e, acc)) {
| Some (expr) => expr
| None =>
match (e) {
| <[ $e1 in $e2 ]> =>
<[ foreach ($e1 in $e2) $acc ]>
| cond =>
<[ when ($cond) $acc ]>
}
}
});
match (exprs) {
| [<[ $second .. $last ]>] =>
<[ $[ x | x in [$second .. $last]] ]>
| [<[ $first ]>, <[ $second .. $last ]>] =>
<[ $[ x | x in [$first, $second .. $last]] ]>
| _ =>
<[
mutable head = null;
mutable tail = null;
$loops;
if (head == null)
[]
else
head
]>
}
}
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, deniok, Вы писали:
D>>Маленькая поправочка — в Хаскелле это не так.
VD>
...Таким же образом мы могли бы определить Int (целые фиксированного диапазона) и Integer:
VD>data Int = -65532 | ... | -1 | 0 | 1 | ... | 65532 –- ещё псевдо-код
VD>data Integer = ... -2 | -1 | 0 | 1 | 2 ...
VD>где -65532 и 65532 – это максимальное и минимальное целое фиксированного диапазона в данной реализации. Тип Int представляет собой существенно более широкое перечисление, чем Char, однако по-прежнему конечное! В противоположность этому псевдо-код для типа Integer предназначен для описания бесконечного перечисления.
VD>Думаешь вольность автора?
Не, ну это же псевдо-код. Здесь троеточие используется в "бытовом" смысле. Чтобы сделать это "менее" псевдо-кодом, нужно было бы перечислить все конструкторы данных. Но при этом всё равно это осталось бы псевдо-кодом. Ясно, что, поскольку мы должны именовать пользовательские конструкторы данных, то мы не можем создать пользовательское перечисление с бесконечным количеством элементов. Integer встроен и в этом смысле выделяется.
Термином перечисление обозначаются две немного разные вещи (отсюда возможная путаница):
(1) Тип данных, с набором только нуль-арных конструкторов (enumerated type);
(2) Экземпляр класса типа Enum.
Для (1) и только для него достаточно указать deriving Enum, чтобы автоматически получить весь синтаксический сахар арифметических последовательностей:
data Color = Red | Orange | Yellow | Green deriving Enum
дает возможность писать
[Orange ..]
вместо
[Orange, Yellow, Green]
Но бесконечным такое перечисление является только для чисел типа Integer:
[7 ..]
Если чего непонятно, вот ссылка на Report по этому поводу.