Функциональный журнал
Writer
предназначен для результатов, к которым присоединено другое значение, действующее как своего рода журнал.
Одним из распространенных применений для Writers
является запись последовательностей шагов в многопоточных вычислениях,
где стандартные методы императивной регистрации могут привести к чередованию сообщений из разных контекстов.
При этом лог для вычислений Writer
привязан к результату,
поэтому можно запускать параллельные вычисления без смешивания логов.
final case class Writer[W, A](run: () => (W, A))
Функции общего назначения, описывающие шаблоны программ с ведением журнала
object Writer:
extension [W, A](underlying: Writer[W, A])
def map[B](f: A => B): Writer[W, B] =
val (w, a) = underlying.run()
Writer[W, B](() => (w, f(a)))
def flatMap[B](f: A => Writer[W, B])(using monoid: Monoid[W]): Writer[W, B] =
Writer[W, B] { () =>
val (w1, a) = underlying.run()
val (w2, b) = f(a).run()
(monoid.combine(w1, w2), b)
}
def unit[W, A](a: => A)(using monoid: Monoid[W]): Writer[W, A] =
Writer[W, A](() => (monoid.empty, a))
Пример:
unit[String, Int](42).run()
// res0: Tuple2[String, Int] = ("", 42)
Реализация
Реализация в Cats
import cats.data.Writer
import cats.instances.vector.*
val a = Writer(Vector(
"It was the best of times",
"it was the worst of times"
), 1859)
val (log, result) = a.run
// val log: Vector[String] = Vector(It was the best of times, it was the worst of times)
// val result: Int = 1859
Ссылки:
- Category Theory for Programmers - Bartosz Milewski:
- Cats
- Herding Cats
- Learning Scalaz
- Scala with Cats