scalabook

Форк
0
/
affixes.md 
281 строка · 9.7 Кб

Значение аффиксов Scala

Перевод статьи "Build your vocabulary with Scala affixes", автор Ross A. Baker

Ниже приводится объяснение некоторых префиксов и суффиксов в Scala.

Префиксы

bi-

bi - значит "два". Обычно префикс означает обобщение одного параметра типа до двух. Это полезно, когда есть канал ошибок, например Either

.

Functor против Bifunctor:

trait Functor[F[_]]:
def map[A, B](fa: F[A])(f: A => B): F[B]
trait Bifunctor[F[_, _]]:
def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D]

Traverse против Bitraverse.

trait Traverse[F[_]]:
def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]]
trait Bitraverse[F[_, _]]:
def bitraverse[G[_]: Applicative, A, B, C, D]( fab: F[A, B])(f: A => G[C], g: B => G[D]): G[F[C, D]]

Как ни странно, Bimonad не вводит второй параметр, а скорее объединяет категорию и ее двойственность.

trait Bimonad[F[_]] extends Monad[F], Comonad[F]

co-

co-представляет собой категориальную двойственность. Наивный способ думать об этом — «переворачивать стрелки».

FlatMap

(другое имя - Bind) и CoflatMap
(другое имя - Co-Bind).

trait FlatMap[F[_]]:
// F[F[A]] → F[A]
def flatten[A](ffa: F[F[A]]): F[A]
trait CoflatMap[F[_]]:
// F[F[A]] ← F[A]
def coflatten[A](fa: F[A]): F[F[A]]

Есть еще Kleisli и Co-Kleisli. Соответствующие примеры есть в Cats и в ScalaZ.

// A → F[B]
final case class Kleisli[F[_], -A, B](run: A => F[B])
// A ← F[B]
final case class Cokleisli[F[_], B, A](run: F[B] => A)
// equivalently
final case class Cokleisli[F[_], A, B](run: F[A] => B)

contra-

Functor и Contra-Functor:

trait Functor[F[_]]:
def map[A, B](fa: F[A])(f: A => B): F[B]
trait Contravariant[F[_]]:
def contramap[A, B](fa: F[A])(f: B => A): F[B]

di-

Принимая во внимание, что bimap

отображает обе стороны, dimap
противопоставляет одну сторону и отображает другую. Функции с одним аргументом — это простой пример Arrow и Profunctor.

trait Arrow[F[_, _]]:
def dimap[A, B, C, D](fab: F[A, B])(f: C => A)(g: B => D): F[C, D]

flat-

flat

- сглаживает сущности.

trait FlatMap[F[_]]:
def map[A, B](fa: F[A])(f: (A) => B ): F[B]
def flatMap[A, B](fa: F[A])(f: (A) => F[B]): F[B]
// tap[A, B](fa: F[A])(f: (A) => B ): F[A]
def flatTap[A, B](fa: F[A])(f: (A) => F[B]): F[A]

tap

- метод, используемый, когда нужно отбросить результат и не фиксировать эффект (это уже за пределами мира функционального программирования). Но стандартная библиотека определяет tap.

par-

par

- для параллельных операций. В стандартной библиотеке параллельные коллекции выделены в отдельный модуль.

trait ParIterable[+T]
trait ParSeq[+T]
trait ParMap[K, +V]
trait ParSet[T]

В Cats можно использовать класс типов Parallel для "распараллеливания" некоторых операций. Для некоторых монад, таких как IO, это относится к параллельному вычислению. В Parallel[Either]

речь идет о накоплении ошибок, а в Parallel[List]
- о сжатии. В этих случаях ничего не говорится о многопоточности, но они делегируются другому экземпляру Applicative
, чтобы избежать требования последовательного закона монад.

semi-

semi-

используется различными преобразователями монад для операций, которые возвращают базовую монаду вместо преобразованной:

case class OptionT[F[_], A](value: F[Option[A]]):
def flatMap[B](f: (A) => OptionT[F, B])(implicit F: Monad[F]): OptionT[F, B]
def semiflatMap[B](f: (A) => F [B])(implicit F: Monad[F]): OptionT[F, B]

sub-

sub-

используется различными преобразователями монад для операций, которые возвращают внутреннюю монаду вместо преобразованной монады:

case class OptionT[F[_], A](value: F[Option[A]]):
def flatMap[B](f: (A) => OptionT[F, B])(implicit F: Monad[F]): OptionT[F, B]
def subflatMap[B](f: (A) => Option [ B])(implicit F: Functor[F]): OptionT[F, B]

Суффиксы

-A

-A

для операций Applicative.

trait Applicative[F[_]]:
def replicateA[A](n: Int, fa: F[A]): F[List[A]]
def unlessA[A](cond: Boolean)(f: => F[A]): F[Unit]
def whenA[A](cond: Boolean)(f: => F[A]): F[Unit]

-F

-F

для операций Functor-а.

trait Functor[F[_]]:
def ifF[A](fb: F[Boolean])(ifTrue: => A, ifFalse: => A): F[A]

-F

также используется для преобразования значений в более сложный тип. В этом случае можно думать об F-"эффекте". Иногда Functor
- это все, что нужно. Иногда необходимо нечто большее.

object Kleisli:
def liftF[F[_], A, B](x: F[B]): Kleisli[F, A, B]
object OptionT:
def liftF[F[_], A](fa: F[A])(F: Functor[F]): OptionT[F, A]
object IorT:
def liftF[F[_], A, B](fb: F[B])(F: Applicative[F]): IorT[F, A, B]
object ContT:
def liftF[F[_], A, B](mb: M[B])(M: FlatMap[M]): ContT[M, A, B]

Вещи, называемые eval

в Cats-Effect и FS2, очень похожи на liftF
, но нарушает нашу этимологию.

object Resource:
def eval[F[_], A](fa: F[A]): Resource[F, A]
object Stream:
def eval[F[_], O](fo: F[O]): Stream[F, O]

-K

-K

предназначен для "высшего рода" и, как правило, не зависит от того, "что внутри коробки".

MonoidK и Monoid:

trait Monoid[A]:
def combine(x: A, y: A): A
trait MonoidK[F[_]]:
def combineK[A](x: F[A], y: F[A]): F[A]

FunctionK и Function:

trait Function1[-T1, +R]: // или =>
def apply(v1: T1): R
trait FunctionK[F[_], G[_]]: // или ~>
def apply[A](fa: F[A]): G[A]

-L, -R

-L

и -R
обозначают Left
и Right
.

trait Applicative[F[_]]:
// Более известно как `<*`
def productL[A, B](fa: F[A])(fb: F[B]): F[A]
// Более известно как `*>`
def productR[A, B](fa: F[A])(fb: F[B]): F[B]

-M

-M

для монадических операций.

trait Monad[F[_]]:
def ifM(fa: F[Boolean])(ifTrue: => F[B], ifFalse: => F[B]): F[B]
def untilM[G[_], A](f: F[A])(cond: => F[Boolean])(implicit G: Alternative[G]): F[G[A]]
def whileM[G[_], A](p: F[Boolean])(body: => F[A])(implicit G: Alternative[G]): F[G[A]]

-T

-T

предназначен для преобразователей монад.

final case class EitherT[F[_], A, B](value: F[Either[A, B]])
final case class IdT[F[_], A](value: F[A])
final case class IorT[F[_], A, B](value: F[Ior[A, B]])
final case class OptionT[F[_], A](value: F[Option[A]])
final case class WriterT[F[_], L, V](run: F[(L, V)])
// И еще несколько псевдонимов
type ReaderT[F[_], -A, B] = Kleisli[F, A, B]
type StateT[F[_], S, A] = IndexedStateT[F, S, S, A]
type StoreT[W[_], S, A] = RepresentableStoreT[W, [β$2$](S) => β$2$, S, A]

_-

Суффикс подчеркивания обычно означает: "Меня волнует эффект, а не результат внутри". Реализации могут быть оптимизированы, если известно, что вызывающий объект все равно проигнорирует это.

trait Traverse[F[_]]:
def traverse [G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]]
def traverse_[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[Unit]

Ссылки:

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

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

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

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