Re[33]: Is C# becoming a functional language?
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.02.07 03:34
Оценка: +1
Здравствуйте, BulatZiganshin, Вы писали:

BZ>представьте себе сериализатор объекта. он рекурсивно вызывает сериализаторы подобъектов. локальности не получается


Что мен его представлять то? Я его сто раз писал. И ни разу с помощью монад... слава богу.
Объекты вообще не должны знать о сериализаторах. Они или должны содержать код сериализации в самих себе или сериализатор должен быть внешний (изучающий структуру объектов через рефлексию или АПИ компилятора).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Монады от Вадлера. Часть 3
От: Mirrorer  
Дата: 12.02.07 06:39
Оценка:
Здравствуйте, 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 если в операцию сложения передается что-то отличное от чисел)
на третьем этапе добавить локализацию ошибки. То есть показывать позицию в которой ошибка произошла.

На каждом этапе указать что и сколько нужно поменять в коде.
Вроде все.
"Если Вы отличаетесь от меня, то это ничуть мне не вредит — Вы делаете меня богаче". Экзюпери
Re: Монады от Вадлера. Часть 0
От: Vermicious Knid  
Дата: 12.02.07 08:11
Оценка: 131 (5) +1
Здравствуйте, 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)")
Re[2]: Монады от Вадлера. Часть 0
От: Mirrorer  
Дата: 12.02.07 08:21
Оценка:
Здравствуйте, Vermicious Knid, Вы писали:

VK>// имхо незачем замусоривать ast локациями, пусть они будут отдельно

Вот тут кстати +1 Пока ехал на работу, подумал о том, что введение локаций в AST это больше хак к монадам имеющий слабое отношение.

VK>Теперь пример с использованием исключений и без лишней функциональности, полученный из вышепревиденного примера:

Красиво и аккуратно.
"Если Вы отличаетесь от меня, то это ничуть мне не вредит — Вы делаете меня богаче". Экзюпери
Re[35]: Is C# becoming a functional language?
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 12.02.07 09:15
Оценка:
Здравствуйте, VladD2, Вы писали:

L>>Почему опять трудится должен я?


VD>Потому что ты вступился за бездакозательное заявление.


Перечитай мой первый пост. Я указал тебе на то, что ты путаешь IO-монаду и монаду вообще. Сколько раз я должен это повторить, чтобы ты понял, что эмуляция императива IO монады никаким боком не лежит к query монаде?

L>>Потрудись перечитать мой ответ. Что тебе в нём непонятно?


VD>В нем нет ответа на мои вопросы. В частности я просил показать монады в C# и объяснить зачем они вообще нужны в этом фзыке.


Это неправда. Я тебе и показал и объяснил. Объяснил, правда, в другом посте. Если тебя это не устраивает, то ещё раз прошу тебя показать, что ИМЕННО в моём ответе тебя не устраивает. Спор получается в стиле

— покажи где?
— вот, например.
— нет ты покажи где.

VD>>>Или то основание, что люди подглядели общую идею в Хаскеле где ее реализация была сделана через монады достаточно чтобы считать что в C# появились монады?


VD>При том что единственная разумная мысль в ваших с ИвелЧилдом рассуждениях была ссылка на фразу о том, что идея LINQ навеяна квэри-компрехеншоном из Хаскеля.


В хаскеле нет такого понятия.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[34]: Is C# becoming a functional language?
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.02.07 09:22
Оценка: +2
Здравствуйте, 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
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[33]: Is C# becoming a functional language?
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 12.02.07 09:35
Оценка:
Здравствуйте, VladD2, Вы писали:

L>>Да (в смысле, прямой ответ — да).


VD>Этого достаточно. Далее остается применить прицип Оккама.


При прочих равных — согласен.

L>> Твоё решение, например, более легкое для твоего понимания. Это что нибудь меняет?


VD>Естественно. Я не фанат функциональщик который будет делать вид, что все очевидно там где все запутанно.


Путаешься в монадах? Не используй Хаскель, проблем то.

VD> Таких как ты найдутся еденицы, такик как я подавляющее больинство.


Спасибо. Для меня это комплимент.

VD>Именно от того ФЯ и сидят в заднице. Они делались людми с мягко говоря сильно отличающейстя психикой.


У кого как. У меня вот ФЯ в голове сидят. А насчёт психики — ну да, человек должен отличаться, чтобы увидеть что то неувиденное другими. Это же хорошо.

L>> Легкость в, повторю, первоначальном понимании по твоему является наиважнейшим и единственным фактором при выборе решения?


VD>При выборе языка. При принятии решения возиться с ним или бросить. Да и вообще при принятии решений. Из двух решений всегда надо выбрить более простой и понятное если коенчнь оно подходит. Тут я с тов. Оккамом совершенно согласен.


Нет. Из двух решений всегда надо выбирать подходящее. Подходящее для достижения цели. Простота и понятность — это немаловажные, но частности. Они учитываются при определении — подходит ли решение для достижения цели и насколько хорошо, но не являются определяющими.

Если для тебя это по другому — ну что ж? Может твоя цель — достижение простоты и понятности
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[34]: Is C# becoming a functional language?
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 12.02.07 09:46
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Разница огромна. Разница в том, что булшит с realworld из серии "это нужно запомнить" и поймут такие решения (точнее даже заходят понимать) далеко не все (точнее мало кто).


Да не нужно этого запоминать. Даже знать то об этом не нужно. Другое дело, что те, кто пишет — хочет знать. Такие уж они люди — любопытные. Если они не понимают — они спрашивают.

L>>Что тебя смущает, не пойму? Выглядит код как императивный, компилируется и работает как императивный, что ещё надо то?


Ответишь на этот вопрос? Может разберёмся, что именно тебе не понятно.

L>>Не придумывай. Дело не в том, что уменьшение не благо, а в том, что это просто невозможно. Во всём остальном числа (целые) ведут себя как обычные перечисления.


VD>От, блин, а мужики то и не знали. Арабы хрен знает сколько лет назад придумали позиционную систему счисления и пользуются ее. Описываенся она на раз. А у Хаскеля идеологические проблемы. Впроче, как всегда. Вот по этому я и говорию, что это интеллектуальное извращение и самообман. Попытка отгородиться от окружающего мира шорами.


И? Каким образом позиционная система счисления позволяет нам записывать перечисление?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[35]: Is C# becoming a functional language?
От: BulatZiganshin  
Дата: 12.02.07 09:50
Оценка: :)
S>Вот мне, к примеру, жутко интересно, что общего у Linq и монад. Мое несовершенное понимаение монад сводится к чему-то вроде "способ управлять композицией функций". В Linq ничего похожего на управление способом композиции функций нет.
S>Вот что такое Linq:
S>1. Extension Methods (жизненно важны для того, чтобы запросы могли работать по любым коллекциям, в том числе и самым абстрактным)

S>Из этого списка сходство с возможностями монад имеет только п.4, и то это весьма отдаленное сходство. Если ты так хорошо понимаешь суть сходства Linq и монад, тебе не составит труда кратко обозначить, какие из перечисленных мной возможностей связывают между собой эти понятия. Не отвечая вопросом на вопрос и не ссылаясь на ссылки на цитаты. А?


как я понимаю, композиция этих extension methods в haskelдВи делалась как раз с помощтю монады. что давало возможность писать императвиный код внутри этого как бы sql-запроса. можежь сравнить это с List monad — она перечисляет все значения в списке и позволет тебе выполнить какие-то вычисления над ними, или отфильтровать их
Люди, я люблю вас! Будьте бдительны!!!
Re[35]: Is C# becoming a functional language?
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 12.02.07 10:57
Оценка: 13 (2) -1
Здравствуйте, 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 и монад, тебе не составит труда кратко обозначить, какие из перечисленных мной возможностей связывают между собой эти понятия. Не отвечая вопросом на вопрос и не ссылаясь на ссылки на цитаты. А?


Я это сделал ещё в том своём посте. В этом всего лишь разжевал. Если твоя цель — не флейм, то велкам обсудить. Если флейм — то велкам бросаться помидорами
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[36]: Is C# becoming a functional language?
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.02.07 12:40
Оценка: +2
Здравствуйте, 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
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[36]: Is C# becoming a functional language?
От: GlebZ Россия  
Дата: 12.02.07 13:02
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Вот и всё. От монад мы легко пришли к LINQ — я показал, что у них есть общего?

А почему бы не через continuations? Можно доказать то же самое — но без термина монада.
Re[30]: Is C# becoming a functional language?
От: GlebZ Россия  
Дата: 12.02.07 13:10
Оценка: 19 (2) +1
Здравствуйте, VladD2, Вы писали:

VD>Люди принимают догмат "чистоты", но сразу же придумывают другой догамт позволяющий эту чистоту обойти. Казалось бы так все просто. В ФЯ любая функция при одном наборе аргументов обязана вернуть один определенный результат. Это помогает во многих случаях. Там распраллеливание, простота отладки, и еще много чего, но вот увы это не вяжется с реальным миром. В любом ООЯ мы просто создали бы объект в который положили бы ссылку на перменную или, как это предлагаешь ты, на хитрый объект сервис-локатор, но увы у нас догмы. Мы не может это сделать. Тогда мы придумываем хитрую чтоуку называем ее поумнее и вуаля обходим наши же ограничения.

Влад. Для начала нужно понять что такое догмат "чистоты" в особенности со стороны компилятора. Это не Lazy. Lazy — всего лишь одна из оптимизаций. Догмат чистоты — это совершенная простота уравнений доступных компилятору. Программу состоящую из терминов atom, sequence и function — можно представить и в виде системы комбинаторных уравнений и в виде графа. И соответвенно преобразовать данный граф автоматически к наиболее эффективному виду. Фактически, это теоретическая возможность построения оптимизатора по сравнению с которым оптимизаторы императивных языков — дети неразумные. И собственно к этому все и движется. Только там слишком много NP задач. Во многом, это похоже на ситуацию с оптимизацией SQL.
В теоретическом будущем, ситуация с pure functional и императивным языком, будет такая же как с C и ассемблером. На ассемблере можно делать очень эффективные программы — но для этого необходимы знание не меньшие чем у разработчиков компилятора C.
Если отказаться от догмата — то нужно отказаться от этого будущего.
А монады — непротиворечат pure. Они лишь вводят новый закон нетранзитивности.
Re[37]: Is C# becoming a functional language?
От: palm mute  
Дата: 12.02.07 13:14
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>А почему бы не через continuations? Можно доказать то же самое — но без термина монада.

continuations выражаются через монады .
Re[31]: Is C# becoming a functional language?
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 12.02.07 13:18
Оценка:
GlebZ,

GZ>Если отказаться от догмата — то нужно отказаться от этого будущего.

GZ>А монады — непротиворечат pure. Они лишь вводят новый закон нетранзитивности.

А что за закон такой? Ты наверное хотел сказать "вводят отношение частичного порядка"?
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[38]: Is C# becoming a functional language?
От: Mirrorer  
Дата: 12.02.07 13:20
Оценка:
Здравствуйте, palm mute, Вы писали:

PM>continuations выражаются через монады .

Насколько я понял(возможно ошибочно) из статьи Вадлера обратное тоже справедливо
"Если Вы отличаетесь от меня, то это ничуть мне не вредит — Вы делаете меня богаче". Экзюпери
Re[37]: Is C# becoming a functional language?
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 12.02.07 13:20
Оценка: -1 :)
Здравствуйте, 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>Тебя просили разжевать очень-очень много раз.


Но только ты показал, что именно не понятно
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[37]: Is C# becoming a functional language?
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 12.02.07 13:20
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>А почему бы не через continuations? Можно доказать то же самое — но без термина монада.


Кто то спорит?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[32]: Is C# becoming a functional language?
От: GlebZ Россия  
Дата: 12.02.07 14:04
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>А что за закон такой? Ты наверное хотел сказать "вводят отношение частичного порядка"?

Возможно. Я в математике монад не большой дока. Просто пришло на ум из другой области, если множество (а можно сказать и функции) нетранзитивно, то трансформировать(менять местами) их нельзя. Частичный порядок — несколько другая вещь. Если есть, можешь дать ссылку на описание мат. основы монад?
Re[33]: Is C# becoming a functional language?
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 12.02.07 14:16
Оценка: 19 (2) +1
Здравствуйте, GlebZ, Вы писали:

GZ>Если есть, можешь дать ссылку на описание мат. основы монад?


Монады взяты из теории категорий.
Тут описание как раз согласно ТК
Если с ТК не знаком, прочти The Haskell Programmer's Guide to the IO Monad — Don't Panic. Там с нуля, даже я понял.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.