scalabook

Форк
0
/
contravariant-functor.md 
100 строк · 4.0 Кб

Контравариантный функтор

Формальное определение

Контравариантный функтор (F

) похож на функтор, только с противоположной операцией cmap
:

  • cmap(b: F[B])(f: A => B): F[A]
    .

Контравариантный функтор создает новые экземпляры классов типов, добавляя функцию в начало цепочки преобразований, в отличие от функтора, который добавляет её в конец.

Законы контравариантного функтора:

  • Identity (тождественность): Если определен метод идентификации id
    такой, что: id(a) == a
    , тогда cmap(fa)(id) == fa
    .
  • Composition (композиция): Если определены два метода f: A => B
    и g: B => C
    , тогда cmap(cmap(fc)(g))(f) == cmap(fc)(g(f(_)))
    .

Определение в виде кода на Scala

trait ContravariantFunctor[F[_]] extends InvariantFunctor[F]:
self =>
def cmap[A, B](b: F[B])(f: A => B): F[A]
def contramap[A, B](b: F[B])(f: A => B): F[A] = cmap(b)(f)
extension [A](fa: F[A]) override def xmap[B](f: A => B, g: B => A): F[B] = cmap(fa)(g)
/** Композиция двух контравариантных функторов ковариантна */
def compose[G[_]: ContravariantFunctor]: Functor[[X] =>> F[G[X]]] =
new Functor[[X] =>> F[G[X]]]:
private val g = summon[ContravariantFunctor[G]]
extension [A](as: F[G[A]]) def map[B](f: A => B): F[G[B]] = cmap(as)(gb => g.cmap(gb)(f))
/** Композиция контравариантного и ковариантного функторов контравариантна */
def icompose[G[_]: Functor]: ContravariantFunctor[[X] =>> F[G[X]]] =
new ContravariantFunctor[[X] =>> F[G[X]]]:
private val g = summon[Functor[G]]
def cmap[A, B](fa: F[G[B]])(f: A => B): F[G[A]] = self.cmap(fa)(g.lift(f))
/** Произведение двух контравариантных функторов контравариантно */
def product[G[_]: ContravariantFunctor]: ContravariantFunctor[[X] =>> (F[X], G[X])] =
new ContravariantFunctor[[X] =>> (F[X], G[X])]:
private val g = summon[ContravariantFunctor[G]]
def cmap[A, B](fa: (F[B], G[B]))(f: A => B): (F[A], G[A]) =
(self.contramap(fa._1)(f), g.contramap(fa._2)(f))

Примеры

Унарная функция

given functionContravariantFunctor[R]: ContravariantFunctor[[X] =>> Function1[X, R]] with
def cmap[A, B](function: B => R)(f: A => B): A => R =
a => function(f(a))

Предикат

Частным случаем предыдущего примера является предикат:

trait Predicate[A] extends Function1[A, Boolean]
given ContravariantFunctor[Predicate] with
def cmap[A, B](b: Predicate[B])(f: A => B): Predicate[A] =
a => b(f(a))

Реализация

Реализация в Cats

import cats.syntax.contravariant.*
import cats.Show
val showString = Show[String]
showString
.contramap[Symbol](sym => s"'${sym.name}")
.show(Symbol("dave"))
// val res0: String = 'dave

Ссылки:

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.