<commit_before>package org.atnos.eff

import cats._
import data._
import cats.implicits._
import Eff._
import Interpret._

/**
 * Effect for logging values alongside computations
 *
 * Compared to traditional Writer monad which accumulates values by default
 * this effect can be interpreted in different ways:
 *
 *  - log values to the console or to a file as soon as they are produced
 *  - accumulate values in a list
 *
 */
trait WriterEffect extends
  WriterCreation with
  WriterInterpretation

object WriterEffect extends WriterEffect

trait WriterCreation {

  /** write a given value */
  def tell[R, O](o: O)(implicit member: Writer[O, *] |= R): Eff[R, Unit] =
    send[Writer[O, *], R, Unit](Writer(o, ()))

}

object WriterCreation extends WriterCreation

trait WriterInterpretation {

  /**
   * run a writer effect and return the list of written values
   *
   * This uses a ListBuffer internally to append values
   */
  def runWriter[R, U, O, A, B](w: Eff[R, A])(implicit m: Member.Aux[Writer[O, *], R, U]): Eff[U, (A, List[O])] =
    runWriterFold(w)(ListFold[O])

  /**
   * More general fold of runWriter where we can use a fold to accumulate values in a mutable buffer
   */
  def runWriterFold[R, U, O, A, B](w: Eff[R, A])(fold: RightFold[O, B])(implicit m: Member.Aux[Writer[O, *], R, U]): Eff[U, (A, B)] = {
    val executed =
      Interpret.runInterpreter(w)(new Interpreter[Writer[O, *], U, A, (A, fold.S)] {
        def onPure(a: A): Eff[U, (A, fold.S)] =
          Eff.pure((a, fold.init))

        def onEffect[X](ox: Writer[O, X], continuation: Continuation[U, X, (A, fold.S)]): Eff[U, (A, fold.S)] = {
          val (o, x) = ox.run
          Eff.impure(x, continuation, { case (a, s) => (a, fold.fold(o, s)) })
        }

        def onLastEffect[X](x: Writer[O, X], continuation: Continuation[U, X, Unit]): Eff[U, Unit] =
          Eff.pure(())

        def onApplicativeEffect[X, T[_] : Traverse](xs: T[Writer[O, X]], continuation: Continuation[U, T[X], (A, fold.S)]): Eff[U, (A, fold.S)] = {
          val os = new collection.mutable.ListBuffer[O]
          val values = xs.map { w: Writer[O, X] =>
            val (o, x) = w.run
            os.append(o)
            x
          }

          Eff.impure(values, continuation, { case (a, s) => (a, os.toList.foldLeft(s) { (res, o) => fold.fold(o, res) }) })
        }

      })

    executed.map { case (a, s) => (a, fold.finalize(s)) }
  }

  /**
   * Run a side-effecting fold
   */
  def runWriterUnsafe[R, U, O, A](w: Eff[R, A])(f: O => Unit)(implicit m: Member.Aux[Writer[O, *], R, U]): Eff[U, A] =
    interpretUnsafe(w)(new SideEffect[Writer[O, *]] {<commit_msg>prepare dotty<commit_after>package org.atnos.eff

import cats._
import data._
import cats.implicits._
import Eff._
import Interpret._

/**
 * Effect for logging values alongside computations
 *
 * Compared to traditional Writer monad which accumulates values by default
 * this effect can be interpreted in different ways:
 *
 *  - log values to the console or to a file as soon as they are produced
 *  - accumulate values in a list
 *
 */
trait WriterEffect extends
  WriterCreation with
  WriterInterpretation

object WriterEffect extends WriterEffect

trait WriterCreation {

  /** write a given value */
  def tell[R, O](o: O)(implicit member: Writer[O, *] |= R): Eff[R, Unit] =
    send[Writer[O, *], R, Unit](Writer(o, ()))

}

object WriterCreation extends WriterCreation

trait WriterInterpretation {

  /**
   * run a writer effect and return the list of written values
   *
   * This uses a ListBuffer internally to append values
   */
  def runWriter[R, U, O, A, B](w: Eff[R, A])(implicit m: Member.Aux[Writer[O, *], R, U]): Eff[U, (A, List[O])] =
    runWriterFold(w)(ListFold[O])

  /**
   * More general fold of runWriter where we can use a fold to accumulate values in a mutable buffer
   */
  def runWriterFold[R, U, O, A, B](w: Eff[R, A])(fold: RightFold[O, B])(implicit m: Member.Aux[Writer[O, *], R, U]): Eff[U, (A, B)] = {
    val executed =
      Interpret.runInterpreter(w)(new Interpreter[Writer[O, *], U, A, (A, fold.S)] {
        def onPure(a: A): Eff[U, (A, fold.S)] =
          Eff.pure((a, fold.init))

        def onEffect[X](ox: Writer[O, X], continuation: Continuation[U, X, (A, fold.S)]): Eff[U, (A, fold.S)] = {
          val (o, x) = ox.run
          Eff.impure(x, continuation, { case (a, s) => (a, fold.fold(o, s)) })
        }

        def onLastEffect[X](x: Writer[O, X], continuation: Continuation[U, X, Unit]): Eff[U, Unit] =
          Eff.pure(())

        def onApplicativeEffect[X, T[_] : Traverse](xs: T[Writer[O, X]], continuation: Continuation[U, T[X], (A, fold.S)]): Eff[U, (A, fold.S)] = {
          val os = new collection.mutable.ListBuffer[O]
          val values = xs.map { w =>
            val (o, x) = w.run
            os.append(o)
            x
          }

          Eff.impure(values, continuation, { case (a, s) => (a, os.toList.foldLeft(s) { (res, o) => fold.fold(o, res) }) })
        }

      })

    executed.map { case (a, s) => (a, fold.finalize(s)) }
  }

  /**
   * Run a side-effecting fold
   */
  def runWriterUnsafe[R, U, O, A](w: Eff[R, A])(f: O => Unit)(implicit m: Member.Aux[Writer[O, *], R, U]): Eff[U, A] =
    interpretUnsafe(w)(new SideEffect[Writer[O, *]] {
{'fraction_non_alphanumeric': 0.16370510396975424, 'fraction_numerical': 0.0, 'mean_word_length': 2.9367559523809526, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6341665', 'n_tokens_mistral': 1904, 'n_tokens_neox': 1869, 'n_words': 557}