Здравствуйте, Sinclair, Вы писали:
S>Так и есть. Всё отличие "нового" кода от "старого" — это замена части аргументов с X на Monad<X>. А дальше начинаем замены.
S>Что смущает-то? Если брать "обычный" процесс разрешения имён из языка вроде C++, то всё работает почти как обычно. Вот мы видим обращение к somefunction(expression), где expression имеет статический тип Monad<X>. Если у нас в scope есть подходящая функция с таким именем, принимающая Monad<X>, то всё в порядке. Если нет — начинаем искать функцию с таким же именем, принимающую X. Если нашли — то смотрим на тип результата. Если он уже Monad<Y>, то заменяем somefunction(expression) на bind(somefunction)(expression). Если тип результата Y, то заменяем somefunction на bind(unit(somefunction))(expression).
S>После этого процесс вывода типов продолжается дальше как обычно.
S>Для многоаргументных функций всё это несколько осложняется, но в целом принцип точно такой же.
Ну так а в каком языке подобное возможно? ) И если предположим возможно, то благодаря каким-то особым свойствам языка или благодаря особым свойствам монад? )
S>Странно. Мне казалось, что у неё сигнатура (в терминах C#) именно
S>S>Function<Monad<A>, Monad<B>> bind(Function<A, Monad<B>> func)
S>
Нет, bind возвращает Monad<B> и именно поэтому можно писать код вида monad>>=func1>>=func2>>=func3. И кстати как раз заменой подобного и является do сахар в Хаскеле, ну разве что он позволяет ещё вставить другие вызовы между элементами цепочки.