{"id":51628021,"url":"https://github.com/zpnst/monads","last_synced_at":"2026-07-13T03:02:09.256Z","repository":{"id":367385139,"uuid":"1266575750","full_name":"zpnst/monads","owner":"zpnst","description":"Monads: A Comprehensive Guide on Haskell","archived":false,"fork":false,"pushed_at":"2026-06-25T18:26:31.000Z","size":5,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-25T20:12:57.924Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zpnst.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-11T18:46:27.000Z","updated_at":"2026-06-25T18:26:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/zpnst/monads","commit_stats":null,"previous_names":["zpnst/monads"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/zpnst/monads","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zpnst%2Fmonads","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zpnst%2Fmonads/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zpnst%2Fmonads/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zpnst%2Fmonads/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zpnst","download_url":"https://codeload.github.com/zpnst/monads/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zpnst%2Fmonads/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35408466,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-13T02:00:06.543Z","response_time":119,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-13T03:02:08.556Z","updated_at":"2026-07-13T03:02:09.245Z","avatar_url":"https://github.com/zpnst.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Monads\n\n#### ... in work ... draft ...\n\n## Основные монады: IO, Maybe, Either, List\n\n### IO-монада:\n\nВажнейшая монада в Haskell, которая позволяет взаимодействовать программе на Haskell с внешним миром.\n\nНачнём с того что Haskell это чистый функциональный язык, возьмем это за аксиому. Поэтому компилятор строит свои оптимизации учитывая эту аксиому и чтобы построить систему ввода/вывода пришлось построить некую надстройку костыль в рантайме языка.\n\nHaskell обладает ссылочной прозрачностью и ленивостью и дабы, учитывая это, посмтроить IO-систему, нам нужно после каждого IO action возвращать возвращать некое значение, что предотвратит оптимизацию по ссылочной прозрачности и ACTIONS будут восприниматься как разные, а порядок вычислений гарантируется не только возвращением некого значения но ещё и передачей этого значения дальше в конвейер дабы дерево ссылок было жестко связано!\n\n```haskell\n-- irwt - initial state of the real world\n\u003e\u003e= :: IO a -\u003e (a -\u003e IO b) -\u003e IO b\nrwt \u003e\u003e= foo = \\irwt -\u003e\nlet (ch, rwt2) = rwt irwt in\nfoo ch rwt2\n\n```\n\nТут мы возвращаем следующее некое значение (состояние мира) дабы ПОБЕДИТЬ ссылочную прозрачность а точнее оптимизации компилятора, базирующиеся на ней и передаем это состояние возвращенное дальше дабы связать порядок операций и гарантировать их упорядоченно выполнение и ПОБЕДИТЬ ленивость\n\n  ```haskell\nnewtype IO a = RealWorld -\u003e (a, RealWorld)\n  ```\n\nА вот и это значение, состояние мира, которое меняется при выполнении какого-либо IO-action, будь то вывод в терминал или взаимодействие с сетью.\n### Maybe/Either-монады:\n\nОбъединим их в одно, так как и то и то позволяет обрабатывать ошибки в функциональном коде, и то и то оборачивает конвейер операций в БЕЗОПАСНУЮ обертку обработки ошибок, только если Maybe на каком-то этапе заметил ошибку то он до конца протаскивает Nothing и мы не знаем на каком именно шаге конвейера произошла ошибка, а вот с Either мы можем зафиксировать Шаг!!! Это их единственное отличие\n\n```haskell\ndata Maybe a = Nothing | Just a\ndata Either a b = Left a | Right b\n```\n\nА так, что то что то действует как обёртка над значением, которого может им не быть из-за ошибки выполнения например функции которое это значение порождает!!!!\n### Списковы монады (Lists):\n\n  \nСписочные монады семантически являются функциональной заменой вложенных списков в императивных языках и concat в их реализации нужен только для того, что убрать вложенность порожденную только для того, чтобы воспринимать тип списка за монаду из математического определения монады!!!\n\n```haskell\ninstance Monad List where\n\t-- (\u003e\u003e=) :: ![a]! -\u003e (a -\u003e ![b]!) -\u003e ![b]!\n\txs \u003e\u003e= f = concat $ map f xs\n```\n\n### Про оператор (\u003e\u003e=):\n\nОператор \u003e\u003e= (bind), то есть оператор связывания делает ровно то, что отражено в названии, связывает РАСПАКОВАННЫЙ результат левой монады с правой монады, то есть предшествующей с последующей и дает возможность КАК БЫ использовать распакованное значение левой монады ВНУТРИ правой монады с внутренним значением правой монады, вот, например, монада Maybe:\n\n```haskell\ninstance Monad Maybe where\n\t-- \u003e\u003e= :: Maybe a -\u003e (a -\u003e Maybe b) -\u003e Maybe b\n\tJust v \u003e\u003e= f = f v\n\tNothing \u003e\u003e= _ = Nothing\n```\n\nМы распаковываем значение v и скармливаем его функции, которая, используя его, продуцирует новую монаду! Иначе, если значение Nothing, протягиваем этот Nothing до конца цепочки.\n\nПочти аналогично дела обстоят и с Either\n\n```haskell\ninstance Monad (Either e) where\n\t-- \u003e\u003e= :: Either e a -\u003e (a -\u003e Either e b) -\u003e Either e b\n\tLeft err \u003e\u003e= _ = Left err\n\tRight v \u003e\u003e= f = f v\n```\n\nНо вот только тут мы захватываем левое значение, так как конструктор типов Either имеет два типа-параметра a и b, то есть\n\n```haskell\ndata Either a b = Left a | Right b\n````\n\nА класс типов монады ждёт конструктор типов с одним аргументом\n\n```haskell\nclass Monad m where\n\t(\u003e\u003e=) :: m a -\u003e (a -\u003e m b) -\u003e m b\n```\n\nНам нужно зафиксировать ошибочный аргумент, что это значит?\n\nКонструкторы данных это просто функции:\n\n```haskell\nLeft :: e -\u003e Either e a\nRight :: a -\u003e Either e a\n```\n\nПосмотрим ещё раз на определение оператора bind у Either монады:\n\n```haskell\n\ninstance Monad (Either e) where\n\t-- \u003e\u003e= :: Either e a -\u003e (a -\u003e Either e b) -\u003e Either e b\n\tLeft err \u003e\u003e= _ = Left err\n\tRight v \u003e\u003e= f = f v\n```\n\nEither может быть как Left e, так и Right a, так как обе эти функции с подставленным в них аргументом возвращают значение типа Either e a. Но при определении экземпляра класса Монады для Either мы фиксируем аргумент e, то есть частично применяем его к конструктору типов Either.\n\nИ так как функция f принимает на вход значение типа “a”, мы можем применить её только к содержимому конструктора данных Right, так как Right :: a -\u003e Either e a, то есть Right содержит значение типа “a”, \n\nа если мы применим f к err, то получим ошибку, так как Left содержит значение типа “e”, Left :: e -\u003e Either e a, “v” :: a и “err” :: e тут и есть эти значения, которые мы достаём с помощью сопоставления с шаблонами по конструкторам данных конструктора типа Either.\n\nА функция f работает только на успешных значениях типа “a”. Но в то же время, мы можем сопоставить Left и достать err, так как что Left, что Right – это функции, что возвращаю значение типа Either e a.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzpnst%2Fmonads","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzpnst%2Fmonads","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzpnst%2Fmonads/lists"}