доня.
Да, я тоже
Aleksei (astynax)
Аппликатив для того и нужен, чтобы не делать все эти liftAN
Aleksei (astynax)
Отдельные лифты с небольшим N остаются только потому, что они работают быстрее (минус одно заворачивание и разворачивание)
Anonymous
Аппликатив - это урезанная монада. В отличие от монады, где ты вешаешь коллбэки на контейнер,и последующие вычисления зависят от предыдущих - к аппликативу ты не можешь прикрепить коллбэк, ты можешь только склеить два контейнера. Зато эти два контейнера могут разрешаться результатом любом порядке. Итак: аппликатив - дерево вычислений (зависимостей?), монада - последовательность вычислений. Так я это вижу.
Leonid 🦇
($) :: (a -> b) -> a -> b (<$>) :: Functor f => (a -> b) -> f a -> f b (<*>) :: Applicative f => f (a -> b) -> f a -> f b Краткая суть
Aleksei (astynax)
Не надо забивать неокрепшим умам голову контейнерами и колбэками! Ничего этого нет! Именно из-за плохих аналогий такой отстой с монадными туториалами
Aleksei (astynax)
Монада просто позволяет делать композицию типов определенного вида, аппликатив позволяет применять функции определенного вида. При этом "определённый вид", это просто ещё одна переменная в типе. Всё
Aleksei (astynax)
Что уж там конечный программист положит в переменную типа - это его дело. Дело монады дать законы, соблюдая которые, программист получит нормальную композицию
Aleksei (astynax)
И тем монада и отличается от сферического паттерна, что имеет законы.
Aleksei (astynax)
Без законов был бы просто интерфейс для навешивания коллбэков
Aleksei (astynax)
($) :: (a -> b) -> a -> b (<$>) :: Functor f => (a -> b) -> f a -> f b (<*>) :: Applicative f => f (a -> b) -> f a -> f b Краткая суть
($) :: (a -> b) -> a -> b (<$>) :: Functor t => (a -> b) -> t a -> t b (<*>) :: Applicative t => t (a -> b) -> t a -> t b (=<<) :: Monad t => (a -> t b) -> t a -> t b :)
Aleksei (astynax)
Если уж искать в хаскеле паттерны, то Reader - паттерн, и State и Writer
Anonymous
Но внутре-то у ней неонка^W коллбэки!
Aleksei (astynax)
Нет
Aleksei (astynax)
f . g - тут f, это callback чтоли?
Aleksei (astynax)
"Колбэки, это убогая беззаконная реализация монады", а не "монады, это такие коллбэки"
Anonymous
ого
Leonid 🦇
Именем закона, прекратите свои реализации и сдавайтесь!
Anonymous
но законы монад едины
Aleksei (astynax)
"Вы нарушили закон identity и приговариваетесь к пожизненному программированию на PHP!"
Anonymous
Я имел ввиду, что второй-то параметр (>>=) - коллбэк. А монада суть паттерн для последовательности вычислений.
Anonymous
На COBOL
Aleksei (astynax)
Да никакой это не колбек!
Anonymous
... а "продолжение"
Aleksei (astynax)
Это континюэйшн
Anonymous
я вообще нем понял тезиса про колбэк, откуда это вообще
Aleksei (astynax)
"коллбэки", это просто ещё одна плохая аналогия. Как "буррито" и "контейнеры"
Anonymous
не могу понять интуицию, которая за этим стоит
Anonymous
ну ок
Anonymous
"коллбэки", это просто ещё одна плохая аналогия. Как "буррито" и "контейнеры"
тогда нахер не просто колбэки, а любые "монад туториалы" с аналогиями
Anonymous
буррито лол
Aleksei (astynax)
Кажется, что кто-то просто наелся обработки асинхронности в JS и теперь любую передачу функции в параметре считает "коллбэком" :)
кана
Ну типа запустили операцию getLine и сказали мол, что когда она выполнится, нужно выполнить функцию после бинда
кана
Как бы колбеки так неплохо накладываются разве что на io
Leonid 🦇
Тру
Anonymous
монада это шаверма. если вы хоть раз ели шаверму на районе, то знаете что такое монада
Aleksei (astynax)
просто IO в хаскеле, это не "выполнение", это конструирование значения, которое "поймет" только main
Anonymous
Оттуда, что до монад было примерно так: data IO a = PutStrLn String (() -> IO a) (Error -> IO a) | GetLine (String -> IO a) (Error -> IO a) ... А монады явились способом организовать этот беспредел
кана
Таки нет. За счет ленивости нихера там не выполняется сразу. Иначе нельзя было делать бы даже простой if внутри
Aleksei (astynax)
Это не беспредел :) Это преждевременная free monad :)
Leonid 🦇
Какой мультиплеер пошёл, прям deathmatch в чате
Anonymous
а на каком уровне работает магия IO? что если у меня кастомный prelude и никаких инстансов монады я не определял?
кана
Это мне нравится
Aleksei (astynax)
IO, кстати, не требудет монад
Anonymous
Тогда у тебя нет и типа данных IO. И ввода-вывода, соответственно
Leonid 🦇
GHC.Prim
Anonymous
нету магии
ну как нет, ты хочешь сказать IO целиком выражен средствами хаскелла?
Aleksei (astynax)
монада реализована для IO только для того, чтобы поиметь do и композицию
Anonymous
IO, кстати, не требудет монад
так вот вопрос чего он требует
Anonymous
я не понимаю, на каком уровне он определен
Aleksei (astynax)
IO находится за пределами хаскеля. Это конечный продукт, который производит хаскелева программа
Aleksei (astynax)
Программа на хаскеле вообще ничего не делает с вводом-выводом
Aleksei (astynax)
Она просто конструирует "программу на другом языке", которую выполнит интерпретатор встроенный в рантайм - вот он то и делает IO и вообще весь с эффектами и грязью
кана
То есть единственное место, где можно делать эффекты - IO?
Aleksei (astynax)
Эффекты, "повлияющие на внешний мир" - да
Anonymous
видимо, есть просто "эффекты" в широком смысле
Aleksei (astynax)
Эффекты, которые не выйдут за пределы программы - запросто. State тот же
кана
Ну так разве у стейта есть эффект? Он же просто возвращает новый "объект", следовательно иммутабелен, следовательно откуда там эффекты?
Aleksei (astynax)
С точки зрения кода, который назодится в State, происходит явная "мутация состояния"
Aleksei (astynax)
Суть State в разделении работы по поддержке сквозного состояния и кода, это состояние использующего
Aleksei (astynax)
Абстракция, короче
Aleksei (astynax)
Так то всегда можно пачку аргументов протаскивать через все вызовы и писать без State и Reader, но это будет "low level"
Aleksei (astynax)
State же позволяет сказать "вот мы имеет настоящую мутацию, можем инкрементить счётчик в цикле, всё как у императивщиков" в выделенном участке кода, но при этом за пределами stayteful блока оставаться в рамках чистого языка, т.е. иметь композицию, ссылочную целостность, вот это всё
Евгений
IO находится за пределами хаскеля. Это конечный продукт, который производит хаскелева программа
Это только одна точка зрения, а вовсе абсолютная истина. Чем представления об IO как об инкапсуляции линейности RealWorld'а хуже?
Евгений
Всё-таки хаскель это не агда, чтобы смотреть на него как на траслятор
Aleksei (astynax)
Можно запросто откатиться к IO в виде ADT ничего принципиально не изменится. Зааффектится только код с unsafePerformIO
Aleksei (astynax)
Линейность есть и в Identity
Aleksei (astynax)
От реального мира абстрагируемся потому, что там перестаёт работать referential transparency например, и ленивость пропадает. И чтобы можно было рассуждать об остальном коде, он отделён от IO насовсем - поэтому нельзя сделать runIO безопасно, только unsafe
Aleksei (astynax)
То, что IO "в хаскеле" не "выполняется", это объективный факт, всё таки. Любые порождаемые значения внутри IO приведут к ожидаемому эффекту тогда и только тогда, когда их ВЕРНЁТ main - вернёт рантайму, который уже "выполнит". До тех пор, пока main не вернёт значение, значение - первокласное, его можно дублировать, класть в чистые типы, возвращать из чистых функций, не боясь, что где-то не там что-то в консоль напечатается или откроется несуществующий файл
Leonid 🦇
Или портал в ад
Aleksei (astynax)
Или ракеты запустятся
Aleksei (astynax)
Я и не спорю. Я имел в виду, что вычисление в IO конструирует значение, которое потом - за пределами программы - выполнится. Как и в случае со State, где конструируется пайплайн, через который будет протащен state
Евгений
Единственная причина существования IO состоит в том, что RealWorld существует только в линейной форме, а в хаскеле этот факт без тайпкласса никак не записать. И всё
Aleksei (astynax)
IO можно представить в виде Writer, который копит [IOAction]
Aleksei (astynax)
хотя больше на State таки похоже