An open API service indexing awesome lists of open source software.

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

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.