scalabook

Форк
0
96 строк · 3.3 Кб

Compose

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

Compose

объединяет две функции в одну. Функция compose
позволяет реализовать Semigroup и Plus в терминах объединения функций.

Compose

должен удовлетворять следующим законам:

  • Ассоциативность: compose(compose(f, g), h) = compose(f, compose(g, h))

Композиция

Имея стрелку f от a к b и стрелку g от b к c, их композиция представляет собой стрелку, идущую непосредственно от a к c. Другими словами, если имеются две стрелки, цель одной из которых совпадает с источником другой, то всегда можно скомпоновать их, чтобы получить третью стрелку. Обозначается как: \(h = g \circ f\)

Ассоциативность

Предположим, что удалось разложить g на \(j \circ k\). Тогда \(h = (j \circ k) \circ f\) Желательно, чтобы это разложение было таким же, как и \(h = j \circ (k \circ f)\). При этом должна существовать возможность заявить, что h была декомпозирована на три более простые функции \(h = j \circ k \circ f\) и не нужно отслеживать, какая декомпозиция была первой. Это свойство называется ассоциативностью композиции.

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

trait Compose[=>:[_, _]]:
self =>
/** Ассоциативный `=>:` бинарный оператор. */
def compose[A, B, C](f: B =>: C, g: A =>: B): A =>: C
protected[arrow] trait ComposePlus extends Plus[[A] =>> A =>: A]:
def plus[A](f1: A =>: A, f2: => A =>: A): A =>: A = self.compose(f1, f2)
protected[arrow] trait ComposeSemigroup[A] extends Semigroup[A =>: A]:
def combine(f1: A =>: A, f2: A =>: A): A =>: A = self.compose(f1, f2)
def plus: Plus[[A] =>> A =>: A] = new ComposePlus {}
def semigroup[A]: Semigroup[A =>: A] = new ComposeSemigroup {}

Примеры

Функция от одной переменной

given Compose[Function1] with
override def compose[A, B, C](f: B => C, g: A => B): A => C = g andThen f

Реализация

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

import cats.*, cats.data.*, cats.syntax.all.*
lazy val f = (_:Int) + 1
lazy val g = (_:Int) * 100
(f >>> g)(2)
// res0: Int = 300
(f <<< g)(2)
// res1: Int = 201

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

import scalaz.*
import Scalaz.*
val f1 = (_:Int) + 1
val f2 = (_:Int) * 100
(f1 >>> f2)(2) // 300
(f1 <<< f2)(2) // 201

Ссылки:

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

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

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

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