Что такое магазин в скалазе

Я пытаюсь понять Lensэс в scalaz (на удивление не нашел ничего похожего в cats-core) и мне попалось так называемое Store который является псевдонимом типа:

type StoreT[F[_], A, B] = IndexedStoreT[F, A, A, B]
type IndexedStore[I, A, B] = IndexedStoreT[Id, I, A, B]
type Store[A, B] = StoreT[Id, A, B]

куда

final case class IndexedStoreT[F[_], +I, A, B](run: (F[A => B], I))

Вопрос в том, как лечить этот тип? Документация просто ссылается на Lensэс. Может кто-нибудь дать объяснение в нескольких словах?

Для меня это похоже на State монада, где "переход состояния" хранится с функцией F[A => B]

1 ответ

Решение

Store[S,A] это структура, полная As, проиндексированный Sс выдающимся S как своего рода "курсор" в структуру.

Чтобы ответить на вопрос "что это?", Наиболее поучительно посмотреть, какие операции он поддерживает.

Вы можете запросить положение курсора:

_.pos : Store[S,A] => S

Вы можете "посмотреть" на значение под курсором:

_.peek : Store[S,A] => A

И вы можете "искать" для перемещения курсора:

_ seek _ : (Store[S,A], S) => Store[S,A]

Думайте об этом как массив измерений Sгде у вас есть индекс s:S в массив, и вы можете переместить индекс.

Например, Store[(Int,Int), Byte] является двумерным 256-цветным растровым изображением. Вы можете peek в цвете (представленном байтом) пикселя под курсором, и вы можете переместить курсор в другой пиксель, используя seek,

Магазин Comonad

Store[S,_] тоже комонад. Это означает, что он поддерживает следующие операции:

map : (A => B) => (Store[S,A] => Store[S,B])
extend : (Store[S,A] => B) => (Store[S,A] => Store[S,B])
duplicate : Store[S,A] => Store[S, Store[S, A]]

map означает, что вы можете изменить все значения в магазине, используя функцию.

s.extend(f) занимает "локальное" вычисление f, который работает в магазине в определенном месте Sи распространяет его на "глобальные" вычисления, которые работают с хранилищем в любом месте. В примере растрового изображения, если у вас есть функция mean(store) который принимает среднее значение пикселей, непосредственно окружающих курсор в store, затем store.extend(mean) выполнит фильтр Гаусса для всего изображения. Каждый пиксель в новом изображении будет представлять собой среднее значение пикселей, непосредственно окружающих пиксели в этом месте исходного изображения.

s.duplicate дает вам Store[S,Store[S,A]] полон Store[S,A]с, что в каждом месте S имеет копию оригинала Store[S,A] с его курсором в этом месте S,

Отношение к государству

Store двойственный State, Под капотом, State[S,A] действительно S => (A, S), а также Store[S,A] действительно (S => A, S):

State[S,A] ~= S => (A, S)
Store[S,A] ~= (S => A, S)

Оба состоят из двух функторов S => _ а также (_, S), Если вы составите их одним способом, вы получите State[S,_], Если вы составите их по-другому, вы получите Store[S,_],

Я говорил об этом пару раз:

https://www.youtube.com/watch?v=FuOZjYVb7g0

Классный способ использования этой двойственности заключается в том, что если у вас есть магазин и конечный автомат, они уничтожают друг друга. Хранилище управляет конечным автоматом, и, в свою очередь, конечный автомат выбирает значение из хранилища.

def zap[S,A,B](state: State[S,A], store: Store[S,B]): (A,B) = {
  val (a, s) = state.run(store.pos)
  (a, store.seek(s).peek)
}
Другие вопросы по тегам