В глазах программиста Java это выглядит как дикий костыль, тем более ко всему прочему усложняется поддержка и деплой. А в мире пхп такие уродливые решения — норма.
Обязательно попробую как будет время, спасибо. Пока откатился до точки восстановления, т.к. какая-то часть обновлений всё-таки установилась и теперь ноутбук сам просыпается с черным экраном и не реагирует на внешние раздражители кроме зажатой кнопки выключения. Посмотрим, поможет ли откат.
это круто, конечно, что умудрились не повторить ошибку системы типов, которую проектировали четверть века назад. Дженерики тоже сразу сделали, а не как в джаве?
Мы просто просим объект нам дать что есть, само название метода нам говорит «дай»: но не «сделай», не «не отправь», не «создай», не «посчитай». Говорит дай — даем что есть. Это вполне нормально работает в разного рода дата-объектах, ответственность которых как раз давать/нести информацию.
Дай, но откуда брать — никто не говорит. Геттер может вернуть всё, что заблагорассудится объекту — значение поля, или запись из БД. И инкапсуляция говорит о том, что внешний объект не должно беспокоить, откуда это значение берётся.
Конечно, в реальности не всё так радужно — постоянные обращения к бд или другие побочные эффекты могут быть нежелательны, или невозможны в текущем состоянии программы. Но к ООП это прямого отношения не имеет. Здесь уже приходится «принюхиваться» к коду(code smelling), регламентировать поведение методов договорённостями(которые, впрочем, не могут распространяться на код внешних библиотек), исчерпывающей документацией(которая может устареть) и хорошим покрытием тестами.
P.S. По моему, с современным виденьем архитектуры программ, основанном на ООП, что-то не так. Проблемы которые решаются ООП — ложные. Инкапсуляция никак не поможет там, где нужна система эффектов.
Я с этим не спорю. Просто со стороны пользователя это выглядит как наплевательское отношение. Ведь проблема известная, и проблема именно в windows, а не в том как его настроил asus(т.к. она проявляется везде). А перенаправление к вендору в данном случае выглядит как «вот где карту открывали туда и идите». Может это и правильно, но это плохой пользовательский опыт.
Был как-то баг у меня в windows — перестал работать пуск и настройки. Баг оказался известным и ms даже утилиту сделали, которая его фиксит. Только вот эта утилита просто не работала. «База данных плитки повреждена». Windows лицензионная, и я отправился в тех.поддержку ms. Первым делом меня спросили о лицензии, затем развернули со словами «читай лицензионное соглашение и иди в anusasus, т.к. OEM версия». Помог откат до точки восстановления, но удивило такое отношение, когда помочь даже не попытались. У гугла тоже, кстати, поддержка не лучше.
Правда ли, что "<-" из do-нотации «невыразима без do-нотации сама по себе»
do
x <- getSomething
putSomething x
getSomething >>= \x -> putSomething x
getSomething >>= putSomething
В какой именно момент происходят вычисления монадических функций (как сами значения, так и эффекты)?
Зависит от монады. Например выражение:
Just 1 >> Just 2 -- вернёт Just 2
Nothing >> Just 2 -- вернёт Nothing
Такие монады как IO можно представить как способ комбинирования команд. Что-то вроде
command1 >> command2 >> command3
это просто конструкция, которую мы создаём с помощью монад. А исполнена она уже будет отдельно.
Для монады IO применяется общее правило про время вычисления функций (с учётом зависимости по данным через «переменную RealWorld») или нет?
С точки зрения языка, IO от других монад не отличается.
монады это «просто» реализация паттерна call/cc, — это вообще как? Ну т.е. что такое паттерн call/cc я прочитал (передаём функцию «досрочного» возврата в лямбду).
Это неправда. Поведение, аналогичное многим монадам можно воспроизвести через call/cc и наоборот. Но это не значит что монады это реализация call/cc.
IO через монады это сознательный дизайн хаскеля, — но зачем!?
Что-бы была возможность описывать IO действия на чистом ЯП?
Можно посмотреть на вашу монаду MyList, для которой sequence будет «запрещен»?
Смысл в том что я могу написать sequence для [IO a] -> IO [a], но не могу для IO [a] -> [IO a]. Потому что IO не Traversable. Как это сделать для продолжений?
В смысле вывернут? Наоборот!
Ничего не наоборот, а именно так.
Я понимаю, что вы хотите сказать, но то, что вы хотите сказать неверно, в том и дело. a -> a в хаскеле это то же самое, что и a -> a в джаве или в racket (насколько понятие «то же самое» применимо для разных систем типов, конечно же).
a -> a в hs это то же самое, что и Function<A,A> в джаве, я правильно понял? Тогда чему эквивалентно a -> IO a? Тоже Function<A,A>? Из этого выходит что a -> a эквивалентно a -> IO a, т.е. налицо нарушение логики. Так что тут Вы не правы.
Нет, не надо, в том и штука. Какая-нибудь функция вроде (define (f x) (+ x 1)) это в точности то же самое что и f x = x + 1.
Соответственно:
это то же самое до тех пор, пока не появится продолжение.
Никакой нотации не надо. Это обычные ф-и a -> a, они стакаются совершенно обычным образом.
Вы из-за неправильного понимания происходящего создаете проблему там, где ее нет, по факту.
Я уже объяснил какой тип у продолжений. Не вижу смысла ходить по кругу. Функция с продолжением никак не может быть a -> a (в hs).
Не совсем понял, что это значит. Тип зафиксировать? Ну если типы есть просто устанавливаете нужный возвращаемый тип и все. Или что вы имели ввиду?
Да, что-то я совсем не объяснил. Допустим я по каким-то причинам не хочу что-бы кто-то мог сделать из моего Maybe (MyList a) — MyList (Maybe a). Что для этого потребуется?
Совсем нет, в моем коде я просто сперва разворачиваю любой эффект, а потом сворачиваю, как надо. В вашем же случае вам приходится делать вложенный do, да еще и с прибитой очередностью в монадах. У вас объективно в коде больше происходит, тут исключительно эффект утенка.
У меня объективно происходит меньше. У Вас пришлось какие-то теги вводить + codeflow по сути вывернут наизнанку.
Поконкретнее можно? Что и куда вы собрались добавлять? Ну т.е. то что вы говорите не будет работать (если я вас верно понял), я просто, чтобы уточнить, где ошибка.
f :: [Maybe Int] -> Maybe [Int] -> Maybe [Int]
f xs ys = sequence $ do
x <- xs
y <- sequence ys
return $ do
x' <- x
y' <- y
return $ x' + y'
Как то так?
Да нет, без типов обычные программы, по сложности ничем не отличающиеся от программ с типами.
и тс из воздуха вырос? Аннотации типов? В теории, теория не отличается от практики.
Видите, работает, ф-я с типом a -> a
я думал Вы поняли, что я хотел сказать. hs( a -> a ) это не то же самое что java( Function<A,A> ), например. И не то же самое что racket( (-> a a) ).
Что-бы hs функция была эквивалентна java, её нужно переписать как то так: hs( a -> IO a ). А что-бы она была эквивалентна racket — вот так: hs( a -> (a -> IO r) -> IO r ).
По этому я и спрашиваю какую нотацию применить, что-бы стакать такие вот функции?
Я бекендщик. Java. Мне все понятно что написано выше, так что не надо вертеться как уж на сковороде. Научитесь сначала отличать асинхронный и парралельно исполняемый код. А та чушь про синхронизацию вообще никакого отношения к реальности не имеет. И приведенный код не эквивалентен.
Ну а для продолжений зачем какой-то сахар? Просто обычный код пишите и все. Т.е. продолжения без сахара — это вот код выше.
Затем же, зачем и монадам?
Ага, ну во-первых код уже сложнее, чем оригинал с продолжениями, а во-вторых — там было еще два вопроса: как изменить код, чтобы во втором значении был другой порядок монад, и как изменить код, чтобы в результате был другой порядок монад.
эмм. По мне так мой код намного проще.
Изменить просто — добавить sequence к аргументу или результату. А у Вас? + как сделать так, что-бы нельзя было сделать из [Maybe Int] — Maybe [Int]?
А кто обсуждал скрипты?
Просто без типов обычно скрипты. Компилируемый язык без типов вообще глупость сама по себе. Но благо сейчас, с аннотациями типов, смысл появляется.
Смысл в томи состоит, чтобы вынести.
Смысл был в том что-бы можно было писать a -> a. Монады реализуются на уровне языка, и довольно просто, если бы с продолжениями было так-же, то может они бы и смогли конкурировать.
И если бы концепция продолжений была популярна, сделали бы ещё одну нотацию как для стрелок.
В примерах выше нет никакого сахара, с-но десугарить нечего. Сахар можно было бы приделать (пару макросов для удобства), но я намеренно не стал.
В них — нет. Мне интересно в контексте cps как замена монад. А для монад в hs используется сахар. Просто хочу сравнить монады без сахара и cps без сахара в hs. Но это уже я сам, наверное.
nuff said
=(
Так и не надо делать теги. Я говорю про следующее — вот у вас есть два значения x и y с типом List Maybe Number, т.е. двойная монадка. Покажите как вы в ду-нотации например получите при помощи монадок из этих двух значений List Maybe их сумм. Ну и до кучи — как потом поменять код чтобы второе значение было Maybe List вместо List Maybe и как поменять код чтобы результат был Maybe List а не List Maybe.
Ну вообще:
liftM2 (liftM2 (+))
а с do как-то так:
do
x <- xs
y <- ys
return $ do
x' <- x
y' <- y
return $ x' + y'
Так а там выше простой код и поток исполнения. Он по сложности на уровне написания mapM примерно
mapM уже слишком сложно для скрипта, на мой взгляд.
Да так же как выглядит бы и выглядел, почему должен быть как-то по-другому он? Дело-то не в ду-нотации, ду-нотация просто сахар. Дело в используемых конструкциях. В примерах выше нету никакого аналога ду-нотации или чего-то типа того, там просто обычный код.
do нотация это сахар, я не спорю. Просто в каком-нибудь C, что-бы писать код аналогичный hs IO, не нужна do нотация. Так же и в racket для cps. В хаскель она понадобится, если не выносить все функции на уровень cps.
Ну просто как факт примите. Тут ничего видеть или не видеть не надо, это объективная вещь.
Не могу, ибо Вы пока никаких объективных фактов не привели. Сравните их в одинаковых условиях — на одном языке и desugared. На том же хс без do нотации, тогда и можно будет сказать что проще, что сложнее и что как стакается.
Вы hs хорошо знаете? Я средне, с racket вообще не знаком.
(Ну или я сам сравню, когда-нибудь; когда пойму полностью)
Но если конкретно на ваш вопрос ответить, то приведите плиз аналог вот этого кода на хаскеле:
У меня пока не получается. К тому же я не знаю как сделать эти теги =\
(и да, если я не смогу — это ничего хорошего о cps не скажет; ну и обо мне тоже)
я, заметьте, не отрицаю пользы типизации. Но вот эти утверждения из разряда «без типизации невозможно использовать в продакшене» — попросту непрофессионально.
без типов можно работать в продакшене. Но код и «поток исполнения» должны быть простыми.
Скажем так, не то чтобы был какой-то выбор. А что именно вам понятно? Почему предпочли? Какая может быть причина писать более сложный и запутанный код с кучей лишнего, когда можно писать более простой и без лишнего?
интересно, как бы выглядел аналог do нотации для hs? Делся бы куда-нибудь «лишний код»? Всё сразу бы застакалось?
Там нет преобразований, просто любое не-null значение считается just а null — nothing.
Ну да
Все наоборот.
Возможно, но пока я этого не вижу
Нет, не включают.
Объясните
Почему страшная? Наоборот — она с формально-теоретической точки зрения очень красивая и изящная, в отличии от монад, которые исторически появились в качестве костыля.
По мне с точностью до наоборот. Конструкция, родившаяся из особенностей работы интерпретатора. А монады — в результате обобщения. Но мне пока рано судить.
А как можно представить IO в виде продолжения?
Как это ноль? Вы можете просто спокойно писать код, который работает — при этот вам не надо ни тратить время на написание монадический комбинаторов, ни на написание трансформеров, которые прерващают код с монадами в натуральный адъ (продолжения же в отличии от монад композятся).
Преимущества продолжений над монадами очевидны — любой код, который пишется на монадах, пишется на продолжениях проще и понятнее.
О какой понятности речь, если я до сих пор до конца не понял как эта штуковина работает? С tf у меня таких проблем нет(да и стакается там всё неплохо). Плюс отсутствие типизации — и это невозможно использовать в production.
На самом деле понятно почему в hs предпочли именно монады.
Не знаю как это работает. Ваш первый вариант кода(без continuation-mark) основан на динамических преобразованиях, и если туда добавить just/nothing, то всё ломается(или я что-то не так понял). Точно так же у меня пока не получилось скомпоновать два «эффекта» в Cont(из-за того, что r получается разный). Так что судить тут не могу.
Разница огромная. Монады намного более примитивная конструкция, в то время как ваши продолжения(конкретная реализация в racket) уже неявно включают в себя монады(IO, Cont и бог знает какие ещё). С типизацией всё плохо. И какой тогда вообще в этом смысл? От хаскеля _весь_ профит в типизации. А тут есть страшная конструкция, с которой вообще возможно работать только потому, что не надо всё типизировать. Практической пользы от этого ноль.
Поправьте меня, но разве в racket есть возможность написать функцию a -> a, но не a -> ContT IO r a? Естественно, если Вы уже в монаде — то ваш map это монадический mapM?
В глазах программиста Java это выглядит как дикий костыль, тем более ко всему прочему усложняется поддержка и деплой. А в мире пхп такие уродливые решения — норма.
Что-же, видимо придётся обращаться к asus, выяснять почему это обновление windows не встаёт…
Конечно, в реальности не всё так радужно — постоянные обращения к бд или другие побочные эффекты могут быть нежелательны, или невозможны в текущем состоянии программы. Но к ООП это прямого отношения не имеет. Здесь уже приходится «принюхиваться» к коду(code smelling), регламентировать поведение методов договорённостями(которые, впрочем, не могут распространяться на код внешних библиотек), исчерпывающей документацией(которая может устареть) и хорошим покрытием тестами.
P.S. По моему, с современным виденьем архитектуры программ, основанном на ООП, что-то не так. Проблемы которые решаются ООП — ложные. Инкапсуляция никак не поможет там, где нужна система эффектов.
anusasus, т.к. OEM версия». Помог откат до точки восстановления, но удивило такое отношение, когда помочь даже не попытались. У гугла тоже, кстати, поддержка не лучше.Зависит от монады. Например выражение:
Такие монады как IO можно представить как способ комбинирования команд. Что-то вроде
это просто конструкция, которую мы создаём с помощью монад. А исполнена она уже будет отдельно.
С точки зрения языка, IO от других монад не отличается.
Это неправда. Поведение, аналогичное многим монадам можно воспроизвести через call/cc и наоборот. Но это не значит что монады это реализация call/cc.
Что-бы была возможность описывать IO действия на чистом ЯП?
Ничего не наоборот, а именно так.
a -> a в hs это то же самое, что и Function<A,A> в джаве, я правильно понял? Тогда чему эквивалентно a -> IO a? Тоже Function<A,A>? Из этого выходит что a -> a эквивалентно a -> IO a, т.е. налицо нарушение логики. Так что тут Вы не правы.
это то же самое до тех пор, пока не появится продолжение.
Я уже объяснил какой тип у продолжений. Не вижу смысла ходить по кругу. Функция с продолжением никак не может быть a -> a (в hs).
У меня объективно происходит меньше. У Вас пришлось какие-то теги вводить + codeflow по сути вывернут наизнанку.
Как то так?
и тс из воздуха вырос? Аннотации типов? В теории, теория не отличается от практики.
я думал Вы поняли, что я хотел сказать. hs( a -> a ) это не то же самое что java( Function<A,A> ), например. И не то же самое что racket( (-> a a) ).
Что-бы hs функция была эквивалентна java, её нужно переписать как то так: hs( a -> IO a ). А что-бы она была эквивалентна racket — вот так: hs( a -> (a -> IO r) -> IO r ).
По этому я и спрашиваю какую нотацию применить, что-бы стакать такие вот функции?
Я бекендщик. Java. Мне все понятно что написано выше, так что не надо вертеться как уж на сковороде. Научитесь сначала отличать асинхронный и парралельно исполняемый код. А та чушь про синхронизацию вообще никакого отношения к реальности не имеет. И приведенный код не эквивалентен.
эмм. По мне так мой код намного проще.
Изменить просто — добавить sequence к аргументу или результату. А у Вас? + как сделать так, что-бы нельзя было сделать из [Maybe Int] — Maybe [Int]?
Просто без типов обычно скрипты. Компилируемый язык без типов вообще глупость сама по себе. Но благо сейчас, с аннотациями типов, смысл появляется.
Смысл был в том что-бы можно было писать a -> a. Монады реализуются на уровне языка, и довольно просто, если бы с продолжениями было так-же, то может они бы и смогли конкурировать.
И если бы концепция продолжений была популярна, сделали бы ещё одну нотацию как для стрелок.
=(
Ну вообще:
а с do как-то так:
mapM уже слишком сложно для скрипта, на мой взгляд.
do нотация это сахар, я не спорю. Просто в каком-нибудь C, что-бы писать код аналогичный hs IO, не нужна do нотация. Так же и в racket для cps. В хаскель она понадобится, если не выносить все функции на уровень cps.
Вы hs хорошо знаете? Я средне, с racket вообще не знаком.
(Ну или я сам сравню, когда-нибудь; когда пойму полностью)
У меня пока не получается. К тому же я не знаю как сделать эти теги =\
(и да, если я не смогу — это ничего хорошего о cps не скажет; ну и обо мне тоже)
без типов можно работать в продакшене. Но код и «поток исполнения» должны быть простыми.
интересно, как бы выглядел аналог do нотации для hs? Делся бы куда-нибудь «лишний код»? Всё сразу бы застакалось?
Возможно, но пока я этого не вижу
Объясните
По мне с точностью до наоборот. Конструкция, родившаяся из особенностей работы интерпретатора. А монады — в результате обобщения. Но мне пока рано судить.
А как можно представить IO в виде продолжения?
О какой понятности речь, если я до сих пор до конца не понял как эта штуковина работает? С tf у меня таких проблем нет(да и стакается там всё неплохо). Плюс отсутствие типизации — и это невозможно использовать в production.
На самом деле понятно почему в hs предпочли именно монады.
Разница огромная. Монады намного более примитивная конструкция, в то время как ваши продолжения(конкретная реализация в racket) уже неявно включают в себя монады(IO, Cont и бог знает какие ещё). С типизацией всё плохо. И какой тогда вообще в этом смысл? От хаскеля _весь_ профит в типизации. А тут есть страшная конструкция, с которой вообще возможно работать только потому, что не надо всё типизировать. Практической пользы от этого ноль.