https://github.com/zpnst/monads
Monads: A Comprehensive Guide on Haskell
https://github.com/zpnst/monads
Last synced: 5 days ago
JSON representation
Monads: A Comprehensive Guide on Haskell
- Host: GitHub
- URL: https://github.com/zpnst/monads
- Owner: zpnst
- Created: 2026-06-11T18:46:27.000Z (about 1 month ago)
- Default Branch: master
- Last Pushed: 2026-06-25T18:26:31.000Z (23 days ago)
- Last Synced: 2026-06-25T20:12:57.924Z (23 days ago)
- Language: Haskell
- Size: 4.88 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Monads
#### ... in work ... draft ...
## Основные монады: IO, Maybe, Either, List
### IO-монада:
Важнейшая монада в Haskell, которая позволяет взаимодействовать программе на Haskell с внешним миром.
Начнём с того что Haskell это чистый функциональный язык, возьмем это за аксиому. Поэтому компилятор строит свои оптимизации учитывая эту аксиому и чтобы построить систему ввода/вывода пришлось построить некую надстройку костыль в рантайме языка.
Haskell обладает ссылочной прозрачностью и ленивостью и дабы, учитывая это, посмтроить IO-систему, нам нужно после каждого IO action возвращать возвращать некое значение, что предотвратит оптимизацию по ссылочной прозрачности и ACTIONS будут восприниматься как разные, а порядок вычислений гарантируется не только возвращением некого значения но ещё и передачей этого значения дальше в конвейер дабы дерево ссылок было жестко связано!
```haskell
-- irwt - initial state of the real world
>>= :: IO a -> (a -> IO b) -> IO b
rwt >>= foo = \irwt ->
let (ch, rwt2) = rwt irwt in
foo ch rwt2
```
Тут мы возвращаем следующее некое значение (состояние мира) дабы ПОБЕДИТЬ ссылочную прозрачность а точнее оптимизации компилятора, базирующиеся на ней и передаем это состояние возвращенное дальше дабы связать порядок операций и гарантировать их упорядоченно выполнение и ПОБЕДИТЬ ленивость
```haskell
newtype IO a = RealWorld -> (a, RealWorld)
```
А вот и это значение, состояние мира, которое меняется при выполнении какого-либо IO-action, будь то вывод в терминал или взаимодействие с сетью.
### Maybe/Either-монады:
Объединим их в одно, так как и то и то позволяет обрабатывать ошибки в функциональном коде, и то и то оборачивает конвейер операций в БЕЗОПАСНУЮ обертку обработки ошибок, только если Maybe на каком-то этапе заметил ошибку то он до конца протаскивает Nothing и мы не знаем на каком именно шаге конвейера произошла ошибка, а вот с Either мы можем зафиксировать Шаг!!! Это их единственное отличие
```haskell
data Maybe a = Nothing | Just a
data Either a b = Left a | Right b
```
А так, что то что то действует как обёртка над значением, которого может им не быть из-за ошибки выполнения например функции которое это значение порождает!!!!
### Списковы монады (Lists):
Списочные монады семантически являются функциональной заменой вложенных списков в императивных языках и concat в их реализации нужен только для того, что убрать вложенность порожденную только для того, чтобы воспринимать тип списка за монаду из математического определения монады!!!
```haskell
instance Monad List where
-- (>>=) :: ![a]! -> (a -> ![b]!) -> ![b]!
xs >>= f = concat $ map f xs
```
### Про оператор (>>=):
Оператор >>= (bind), то есть оператор связывания делает ровно то, что отражено в названии, связывает РАСПАКОВАННЫЙ результат левой монады с правой монады, то есть предшествующей с последующей и дает возможность КАК БЫ использовать распакованное значение левой монады ВНУТРИ правой монады с внутренним значением правой монады, вот, например, монада Maybe:
```haskell
instance Monad Maybe where
-- >>= :: Maybe a -> (a -> Maybe b) -> Maybe b
Just v >>= f = f v
Nothing >>= _ = Nothing
```
Мы распаковываем значение v и скармливаем его функции, которая, используя его, продуцирует новую монаду! Иначе, если значение Nothing, протягиваем этот Nothing до конца цепочки.
Почти аналогично дела обстоят и с Either
```haskell
instance Monad (Either e) where
-- >>= :: Either e a -> (a -> Either e b) -> Either e b
Left err >>= _ = Left err
Right v >>= f = f v
```
Но вот только тут мы захватываем левое значение, так как конструктор типов Either имеет два типа-параметра a и b, то есть
```haskell
data Either a b = Left a | Right b
````
А класс типов монады ждёт конструктор типов с одним аргументом
```haskell
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
```
Нам нужно зафиксировать ошибочный аргумент, что это значит?
Конструкторы данных это просто функции:
```haskell
Left :: e -> Either e a
Right :: a -> Either e a
```
Посмотрим ещё раз на определение оператора bind у Either монады:
```haskell
instance Monad (Either e) where
-- >>= :: Either e a -> (a -> Either e b) -> Either e b
Left err >>= _ = Left err
Right v >>= f = f v
```
Either может быть как Left e, так и Right a, так как обе эти функции с подставленным в них аргументом возвращают значение типа Either e a. Но при определении экземпляра класса Монады для Either мы фиксируем аргумент e, то есть частично применяем его к конструктору типов Either.
И так как функция f принимает на вход значение типа “a”, мы можем применить её только к содержимому конструктора данных Right, так как Right :: a -> Either e a, то есть Right содержит значение типа “a”,
а если мы применим f к err, то получим ошибку, так как Left содержит значение типа “e”, Left :: e -> Either e a, “v” :: a и “err” :: e тут и есть эти значения, которые мы достаём с помощью сопоставления с шаблонами по конструкторам данных конструктора типа Either.
А функция f работает только на успешных значениях типа “a”. Но в то же время, мы можем сопоставить Left и достать err, так как что Left, что Right – это функции, что возвращаю значение типа Either e a.