Pull to refresh

Comments 26

Можно ещё упомянуть, что
a -- [IO] -> b
это стрелки Клейсли, и используя их, можно писать вполне себе:
test :: String -> IO ()
test = runKleisli (Klesli purStrLn . arr (map toUpper) . Kleisli readFile)

Напрягает, правда, необходимость оборачивать функцию.
Спасибо!

Лично я о стрелках Клейсли пока ничего не знаю, но и до них дойдет дело когда-нибудь.
Я тут поковырял ваш пример, переписывая его на стандартных функциях. И никак не получается обойтись без функции bind.

test :: String -> IO ()
test = (putStrLn =<<) . fmap (map toUpper) . readFile
 
main = test "Kleisli.hs"


Вот этот вариант хоть и проходи проверку типов, а не работает (не выводит данных, что занимательно, ведь бытует мнение, что если компилируется, значит почти всегда работает):

test2 = fmap (putStrLn . map toUpper) . readFile


Получается, что стрелки Клейсли — это способ не использовать bind? Правда, я не знаю, как они устроены внутри. Там, может быть, тоже связывание используется.
Не совсем понял, что значит «на стандартных функциях»? Klesli же стандартные.
Если интересует, как они внутри устроены, то код здесь. Внутри там есть bind, конечно.
Стрелки не для того, чтоб не использовать bind, про них имеет смысл почитать отдельно :)
По поводу второго варианта. У вас получается тип IO (IO ())
Т.е. test2 ничего не печатает, он возвращает монадное действие, которое уже печатает. Чтобы реально напечатать надо сделать так:
do
    action <- test2
    action

Или проще:
join test2

Ну, do здесь всего лишь другая запись bind'а, да и в join тот же самый bind:
join x = x >>= id
Без него, получается, никак. Нельзя объехать океан. :)

Говоря «стандартные» я имел в виду, конечно, функции из модуля Prelude. Про стрелки почитал и поразмышлял; на первый взгляд, это то же самое, только в другой форме. Буду изучать дальше.
Так IO специально же так устроено в Хаскеле чтобы его без bind-а нельзя было использовать. В этом собственно основная идея IO и состоит.
И это правильная идея. Если обращаться с IO правильно, монада раскладывает код по слоям. Он становится чище и понятнее. Главное, не желать в любом участке кода побочные эффекты, — пусть они будут сосредоточены где-то в одном слое. Иначе — бардак.
Дай бог хоть бы без них разобраться :)
Эврика! Я понял, зачем нужен Haskell — чтобы писать руководства по монадам: ) А если без шуток, спасибо за перевод. Первое руководство, хоторое хоть как-то пытается привязать монады к программистской интуиции.

Но опять же, проблема в том, что рассказывается сперва о том, как пользоваться монадами (а это интуитивно просто), вместо того, чтобы рассказать, как их проектировать (вот именно это интуитивно очень сложно).

Впрочем, дождусь продолжения. Перевод хороший, даже не полезу оригинал читать.
Вот-вот, проектирование монад — проблема. И я решил ее расколоть на досуге. Упирается дело в то, что не осознаешь, что хочешь получить. Чем должна заниматься монада — непонятно. В своем Adv2Game (учебно-амбициозный проект) я сначала попробовал подход «сверху вниз»: начал придумывать игровой объект, как если бы он был монадой. Было ясно, что нужна State, а также действия над этим объектом должны быть сами по себе монадами. Пробовал вписать эти два требования в игровой объект, поглядывая в AdventureGame — там все очень сурово. Нетрудно догадаться, что ничего не получилось. Однако, подход «снизу вверх», кажется, работает. При нем пишешь сразу функции, не думая о конкретных типах. Сначала получается псевдокод на некотором еще не существующем языке, но он должен делать именно то, что задумывалось. И уже потом начинаешь подгонять под него операторы и функции, чтобы тайпчекер умолк. Монады появляются уже исходя из требований псевдокода, превращая его в валидный код. Но, конечно, без разработки типов данных в монады можно даже не соваться. Важнее типов данных ничего нет.

Тут, впрочем, одним комментарием много не расскажешь. Когда эта дорожка меня куда-нибудь приведет, поделюсь опытом.
Я лично пишу новую монаду тогда, когда она может значительно сократить код, как, например, тут
В статье, правда, не видно сравнения того, что было (а были вызовы с передачей лямбды, внутри которой были такие же вызовы с передачей новых лямбд, выглядело это как большая развесистая лестница) с тем, что стало (фактически простой линейный код).
Да, понимаю. В реализации Lambda The Gathering и в Adv2Game у меня тоже монады, и хотя я пока не научился их делать эффективно, код они структурируют и упрощают. Ту вашу статью видел, конечно. Пример хороший. Кстати, как вы добились той подсветки?
Пропатчил стандартный HsColour, чтобы можно было указывать произвольные цвета в файле конфигурации (а не только 16 стандартных), им и пользуюсь.

Во всех туториалах забывают сказать, что монадой называют просто три функции (конструктор, единица и композиция) и набор ограничений (комопзиция ассоциативна) и всё. Никакой магии. Тут нечего «понимать», это просто удачное наблюдение, что много конструкций в программировании можно описать при помощи этой тройки.
Конечно, интересно почитать, каким образом можно лего вывести эту конструкцию самому (из шаблонов использования или из теории категорий), но именно, что «понимать» тут нечего. А именно то, что постоянно говорят про «понимание» монад и сбивает с толку :)
Вообще-то, не так. Во-первых, не композиция, а применение. Во-вторых, нужно ещё соблюдение аксиомы монадности, которая bind (применение) и return (единицу) связывают. В-третьих, это не просто композиция, это ещё и выполнение неких действий в background. Этим конструкция и интересна.

И понимание монад — это как раз понимание того, как вот этот background засунуть в интерфейс из трёх функций… И это несколько не тривиально. Нафигачить на Си, конечно, нечто с таким интерфейсом — без проблем. А вот нафигачить на Haskell — это уже некий вызов, потому поразминать мозги стоит.
Не знаю приводились ли эти материалы по монадам (на английском):

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/

Да и вообще блог Милевски очень интересное чтиво.
Прекрасная статья, очень доступно написана (лично меня немного смутила середина своей неочевидностью, но начало и концовка очень хороша). В избранное.
Впервые вижу образцы текста на Haskel. Как же он brainfuck напоминает!
Совсем нет. Простой код на Haskell кристально понятен по сравнению с brainfuck. Потому что он максимально приближен к математической нотации. Haskell не стоит изучать с этой статьи, потому что монады — это фигуры высшего пилотажа, кстати, не только в Haskell. Посмотрите мои статьи, — там есть примеры ну очень понятные.
Очень странное место я выбрал для ссылки. По запарке, очевидно. Я имел в виду: Haskell не стоит изучать начиная с руководства о монадах. Лучше посмотрите, например, мои статьи (по той криво поставленной ссылке).
Просьба переводчику — примечания всё ж не сносить вниз.
Мало того, что они тут, в гипертексте, даны в виде ({3}) без гиперссылок, и отнесены в самый конец статьи, далеко от поясняемого текста, так и в данном конкретном случае совершенно не оправданы — ибо фразы примечаний тут очень коротенькие, и легко воспринимались бы в скобочках непосредственно в месте ссылок.
Спасибо, учту.

Тут примечания не очень-то важные, полезной информации практически нет, так что мы немного теряем.
У вас ссылка на 2ую часть кривая
Sign up to leave a comment.

Articles

Change theme settings