Invariant Applicative
InvariantApplicative (инвариантный аппликативный функтор) — это функциональная абстракция,
которая обобщает понятие контейнера, поддерживающего двунаправленные преобразования
(инвариантные отображения) и "обёртывание" значений в контекст с помощью единичных операций
xunit0, xunit1 и т.д.
В отличие от обычного Applicative, который требует ковариантности (возможности преобразовывать значения в одном направлении), инвариантный аппликативный функтор позволяет работать с типами, где преобразования могут быть обратимыми или требовать двустороннего отображения.
Код
trait InvariantFunctor[F[_]]:
extension [A](fa: F[A])
def imap[B](f: A => B, g: B => A): F[B]
trait InvariantApplicative[F[_]] extends InvariantFunctor[F]:
def xunit0[A](a: => A): F[A]
extension [A](fa: => F[A])
def xunit1[B](f: A => B, g: B => A): F[B] =
fa.imap(f, g)
-
Базовые операции:
imap(инвариантное отображение) — преобразуетF[A]вF[B]с помощью пары обратных функцийxunit0— помещает значение в минимальный контекстF(аналогpureв обычномApplicative)
-
Производные операции:
xunit1— комбинацияxunit0иimapдля создания значения в контексте с преобразованием
Законы
- Закон тождественности для
imap:fa.imap(identity, identity) == fa - Закон композиции для
imap:fa.imap(f1, g1).imap(f2, g2) == fa.imap(f1 andThen f2, g2 andThen g1) - Закон единицы для
xunit0:xunit0(a).imap(f, g) == xunit0(f(a))
Когда использовать
Инвариантный Applicative полезен в следующих случаях:
- Работа с двунаправленными преобразованиями (сериализация/десериализация)
- Типы с обратимыми операциями (изоморфизмы, кодирование/декодирование)
- Композиция типов-контейнеров с сохранением возможности обратного преобразования
- Построение DSL для двусторонних трансформаций данных
Схема
classDiagram
class InvariantFunctor~A~{
+imap[B](fa: F[A], f: A => B, g: B => A) F[B]
}
class InvariantApplicative~A~{
+xunit0[A](a: => A) F[A]
}
InvariantFunctor <|-- InvariantApplicative
Ссылки: