Комментарии 26
Можно ещё упомянуть, что
это стрелки Клейсли, и используя их, можно писать вполне себе:
Напрягает, правда, необходимость оборачивать функцию.
a -- [IO] -> b
это стрелки Клейсли, и используя их, можно писать вполне себе:
test :: String -> IO ()
test = runKleisli (Klesli purStrLn . arr (map toUpper) . Kleisli readFile)
Напрягает, правда, необходимость оборачивать функцию.
+2
Спасибо!
Лично я о стрелках Клейсли пока ничего не знаю, но и до них дойдет дело когда-нибудь.
Лично я о стрелках Клейсли пока ничего не знаю, но и до них дойдет дело когда-нибудь.
0
Я тут поковырял ваш пример, переписывая его на стандартных функциях. И никак не получается обойтись без функции bind.
Вот этот вариант хоть и проходи проверку типов, а не работает (не выводит данных, что занимательно, ведь бытует мнение, что если компилируется, значит почти всегда работает):
Получается, что стрелки Клейсли — это способ не использовать bind? Правда, я не знаю, как они устроены внутри. Там, может быть, тоже связывание используется.
test :: String -> IO ()
test = (putStrLn =<<) . fmap (map toUpper) . readFile
main = test "Kleisli.hs"
Вот этот вариант хоть и проходи проверку типов, а не работает (не выводит данных, что занимательно, ведь бытует мнение, что если компилируется, значит почти всегда работает):
test2 = fmap (putStrLn . map toUpper) . readFile
Получается, что стрелки Клейсли — это способ не использовать bind? Правда, я не знаю, как они устроены внутри. Там, может быть, тоже связывание используется.
0
По поводу второго варианта. У вас получается тип
Т.е.
Или проще:
IO (IO ())
Т.е.
test2
ничего не печатает, он возвращает монадное действие, которое уже печатает. Чтобы реально напечатать надо сделать так:do
action <- test2
action
Или проще:
join test2
0
Ну, do здесь всего лишь другая запись bind'а, да и в join тот же самый bind:
join x = x >>= id
Без него, получается, никак. Нельзя объехать океан. :)
Говоря «стандартные» я имел в виду, конечно, функции из модуля Prelude. Про стрелки почитал и поразмышлял; на первый взгляд, это то же самое, только в другой форме. Буду изучать дальше.
join x = x >>= id
Без него, получается, никак. Нельзя объехать океан. :)
Говоря «стандартные» я имел в виду, конечно, функции из модуля Prelude. Про стрелки почитал и поразмышлял; на первый взгляд, это то же самое, только в другой форме. Буду изучать дальше.
0
Так IO специально же так устроено в Хаскеле чтобы его без bind-а нельзя было использовать. В этом собственно основная идея IO и состоит.
+1
Дай бог хоть бы без них разобраться :)
0
Эврика! Я понял, зачем нужен Haskell — чтобы писать руководства по монадам: ) А если без шуток, спасибо за перевод. Первое руководство, хоторое хоть как-то пытается привязать монады к программистской интуиции.
Но опять же, проблема в том, что рассказывается сперва о том, как пользоваться монадами (а это интуитивно просто), вместо того, чтобы рассказать, как их проектировать (вот именно это интуитивно очень сложно).
Впрочем, дождусь продолжения. Перевод хороший, даже не полезу оригинал читать.
Но опять же, проблема в том, что рассказывается сперва о том, как пользоваться монадами (а это интуитивно просто), вместо того, чтобы рассказать, как их проектировать (вот именно это интуитивно очень сложно).
Впрочем, дождусь продолжения. Перевод хороший, даже не полезу оригинал читать.
+2
Вот-вот, проектирование монад — проблема. И я решил ее расколоть на досуге. Упирается дело в то, что не осознаешь, что хочешь получить. Чем должна заниматься монада — непонятно. В своем Adv2Game (учебно-амбициозный проект) я сначала попробовал подход «сверху вниз»: начал придумывать игровой объект, как если бы он был монадой. Было ясно, что нужна State, а также действия над этим объектом должны быть сами по себе монадами. Пробовал вписать эти два требования в игровой объект, поглядывая в AdventureGame — там все очень сурово. Нетрудно догадаться, что ничего не получилось. Однако, подход «снизу вверх», кажется, работает. При нем пишешь сразу функции, не думая о конкретных типах. Сначала получается псевдокод на некотором еще не существующем языке, но он должен делать именно то, что задумывалось. И уже потом начинаешь подгонять под него операторы и функции, чтобы тайпчекер умолк. Монады появляются уже исходя из требований псевдокода, превращая его в валидный код. Но, конечно, без разработки типов данных в монады можно даже не соваться. Важнее типов данных ничего нет.
Тут, впрочем, одним комментарием много не расскажешь. Когда эта дорожка меня куда-нибудь приведет, поделюсь опытом.
Тут, впрочем, одним комментарием много не расскажешь. Когда эта дорожка меня куда-нибудь приведет, поделюсь опытом.
+1
Я лично пишу новую монаду тогда, когда она может значительно сократить код, как, например, тут
В статье, правда, не видно сравнения того, что было (а были вызовы с передачей лямбды, внутри которой были такие же вызовы с передачей новых лямбд, выглядело это как большая развесистая лестница) с тем, что стало (фактически простой линейный код).
В статье, правда, не видно сравнения того, что было (а были вызовы с передачей лямбды, внутри которой были такие же вызовы с передачей новых лямбд, выглядело это как большая развесистая лестница) с тем, что стало (фактически простой линейный код).
0
Да, понимаю. В реализации Lambda The Gathering и в Adv2Game у меня тоже монады, и хотя я пока не научился их делать эффективно, код они структурируют и упрощают. Ту вашу статью видел, конечно. Пример хороший. Кстати, как вы добились той подсветки?
0
* Не AdvantureGame, а LambdaHack.
0
Во всех туториалах забывают сказать, что монадой называют просто три функции (конструктор, единица и композиция) и набор ограничений (комопзиция ассоциативна) и всё. Никакой магии. Тут нечего «понимать», это просто удачное наблюдение, что много конструкций в программировании можно описать при помощи этой тройки.
Конечно, интересно почитать, каким образом можно лего вывести эту конструкцию самому (из шаблонов использования или из теории категорий), но именно, что «понимать» тут нечего. А именно то, что постоянно говорят про «понимание» монад и сбивает с толку :)
Конечно, интересно почитать, каким образом можно лего вывести эту конструкцию самому (из шаблонов использования или из теории категорий), но именно, что «понимать» тут нечего. А именно то, что постоянно говорят про «понимание» монад и сбивает с толку :)
+4
Вообще-то, не так. Во-первых, не композиция, а применение. Во-вторых, нужно ещё соблюдение аксиомы монадности, которая bind (применение) и return (единицу) связывают. В-третьих, это не просто композиция, это ещё и выполнение неких действий в background. Этим конструкция и интересна.
И понимание монад — это как раз понимание того, как вот этот background засунуть в интерфейс из трёх функций… И это несколько не тривиально. Нафигачить на Си, конечно, нечто с таким интерфейсом — без проблем. А вот нафигачить на Haskell — это уже некий вызов, потому поразминать мозги стоит.
И понимание монад — это как раз понимание того, как вот этот background засунуть в интерфейс из трёх функций… И это несколько не тривиально. Нафигачить на Си, конечно, нечто с таким интерфейсом — без проблем. А вот нафигачить на Haskell — это уже некий вызов, потому поразминать мозги стоит.
+1
Не знаю приводились ли эти материалы по монадам (на английском):
bartoszmilewski.wordpress.com/2011/01/09/monads-for-the-curious-programmer-part-1/
bartoszmilewski.wordpress.com/2011/03/14/monads-for-the-curious-programmer-part-2/
bartoszmilewski.wordpress.com/2011/03/17/monads-for-the-curious-programmer-part-3/
но, на мой взгляд, очень качественно поданный материал. Есть также бонус для плюсовиков:
bartoszmilewski.wordpress.com/2011/07/11/monads-in-c/
Да и вообще блог Милевски очень интересное чтиво.
bartoszmilewski.wordpress.com/2011/01/09/monads-for-the-curious-programmer-part-1/
bartoszmilewski.wordpress.com/2011/03/14/monads-for-the-curious-programmer-part-2/
bartoszmilewski.wordpress.com/2011/03/17/monads-for-the-curious-programmer-part-3/
но, на мой взгляд, очень качественно поданный материал. Есть также бонус для плюсовиков:
bartoszmilewski.wordpress.com/2011/07/11/monads-in-c/
Да и вообще блог Милевски очень интересное чтиво.
+1
Прекрасная статья, очень доступно написана (лично меня немного смутила середина своей неочевидностью, но начало и концовка очень хороша). В избранное.
+1
Впервые вижу образцы текста на Haskel. Как же он brainfuck напоминает!
-1
Совсем нет. Простой код на Haskell кристально понятен по сравнению с brainfuck. Потому что он максимально приближен к математической нотации. Haskell не стоит изучать с этой статьи, потому что монады — это фигуры высшего пилотажа, кстати, не только в Haskell. Посмотрите мои статьи, — там есть примеры ну очень понятные.
0
Просьба переводчику — примечания всё ж не сносить вниз.
Мало того, что они тут, в гипертексте, даны в виде ({3}) без гиперссылок, и отнесены в самый конец статьи, далеко от поясняемого текста, так и в данном конкретном случае совершенно не оправданы — ибо фразы примечаний тут очень коротенькие, и легко воспринимались бы в скобочках непосредственно в месте ссылок.
Мало того, что они тут, в гипертексте, даны в виде ({3}) без гиперссылок, и отнесены в самый конец статьи, далеко от поясняемого текста, так и в данном конкретном случае совершенно не оправданы — ибо фразы примечаний тут очень коротенькие, и легко воспринимались бы в скобочках непосредственно в месте ссылок.
+1
У вас ссылка на 2ую часть кривая
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Еще Одно Руководство по Монадам (часть 1: основы)