alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (Reducer.scala)

This example Scala source code file (Reducer.scala) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Scala by Example" TM.

Learn more about this Scala project at its project page.

Java - Scala tags/keywords

conjunction, first, last, monoid, multiplication, option, reducer, reducerinstances, tag, unitreducer, vector

The Reducer.scala Scala example source code

package scalaz

import scalaz.Tags.{Conjunction}


/**
 * A `Reducer[C,M]` is a [[scalaz.Monoid]]`[M]` that maps
 * values of type `C` through `unit` to values of type `M`. A `C-Reducer` may also
 * supply operations which tack on another `C` to an existing `Monoid` `M` on the left
 * or right. These specialized reductions may be more efficient in some scenarios
 * and are used when appropriate by a [[scalaz.Generator]]. The names `cons` and `snoc` work
 * by analogy to the synonymous operations in the list monoid.
 *
 * Minimal definition: `unit` or `snoc`
 *
 * Based on a Haskell library by Edward Kmett
 */
sealed abstract class Reducer[C, M] {
  implicit def monoid: Monoid[M]

  def unit(c: C): M

  /** Faster `append(m, unit(c))`. */
  def snoc(m: M, c: C): M

  /** Faster `append(unit(c), m)`. */
  def cons(c: C, m: M): M

  def zero: M =
    monoid.zero

  def append(a1: M, a2: => M): M =
    monoid.append(a1, a2)

  /** Distribute `C`s to `M` and `N`. */
  def compose[N](r: Reducer[C, N]): Reducer[C, (M, N)] = {
    implicit val m = Reducer.this.monoid
    implicit val n = r.monoid
    new Reducer[C, (M, N)] {

      import std.tuple._

      val monoid = Monoid[(M, N)]

      override def unit(x: C) = (Reducer.this.unit(x), r.unit(x))

      override def snoc(p: (M, N), x: C) = (Reducer.this.snoc(p._1, x), r.snoc(p._2, x))

      override def cons(x: C, p: (M, N)) = (Reducer.this.cons(x, p._1), r.cons(x, p._2))
    }
  }
}
sealed abstract class UnitReducer[C, M] extends Reducer[C, M] {
  implicit def monoid: Monoid[M]
  def unit(c: C): M

  def snoc(m: M, c: C): M = monoid.append(m, unit(c))

  def cons(c: C, m: M): M = monoid.append(unit(c), m)
}

object UnitReducer {
  /** Minimal `Reducer` derived from a monoid and `unit`. */
  def apply[C, M](u: C => M)(implicit mm: Monoid[M]): Reducer[C, M] = new UnitReducer[C, M] {
    val monoid = mm
    def unit(c: C) = u(c)
  }
}

object Reducer extends ReducerInstances {
  /** Reducer derived from `unit`, `cons`, and `snoc`.  Permits more
    * sharing than `UnitReducer.apply`.
    */
  def apply[C, M](u: C => M, cs: C => M => M, sc: M => C => M)(implicit mm: Monoid[M]): Reducer[C, M] =
    reducer(u, cs, sc)
}

sealed abstract class ReducerInstances {

  /** Collect `C`s into a list, in order. */
  implicit def ListReducer[C]: Reducer[C, List[C]] = {
    import std.list._
    unitConsReducer(_ :: Nil, c => c :: _)
  }

  /** Collect `C`s into a stream, in order. */
  implicit def StreamReducer[C]: Reducer[C, Stream[C]] = {
    import std.stream._
    unitConsReducer(Stream(_), c => c #:: _)
  }

  /** Ignore `C`s. */
  implicit def UnitReducer[C]: Reducer[C, Unit] = {
    import std.anyVal._
    unitReducer((_: C) => ())
  }

  /** Collect `C`s into a vector, in order. */
  implicit def VectorReducer[C]: Reducer[C, Vector[C]] = new Reducer[C, Vector[C]]{
    val monoid: Monoid[Vector[C]] = std.vector.vectorMonoid[C]
    def cons(c: C, m: Vector[C]) = c +: m
    def snoc(m: Vector[C], c: C) = m :+ c
    def unit(c: C) = Vector(c)
  }

  /** The "or" monoid. */
  implicit val AnyReducer: Reducer[Boolean, Boolean] = {
    implicit val B = std.anyVal.booleanInstance.disjunction
    unitReducer(x => x)
  }

  import std.anyVal._

  /** The "and" monoid. */
  implicit val AllReducer: Reducer[Boolean, Boolean @@ Conjunction] = unitReducer(b => Tag[Boolean, Conjunction](b))

  /** Accumulate endomorphisms. */
  implicit def EndoReducer[A]: Reducer[A => A, Endo[A]] = unitReducer(Endo(_))

  implicit def DualReducer[A: Monoid]: Reducer[A, A @@ Tags.Dual] = unitReducer(Tags.Dual(_: A))(Dual.dualMonoid[A])

  import Tags.{Multiplication, First, Last}

  implicit val IntProductReducer: Reducer[Int, Int @@ Multiplication] = unitReducer(i => Tag[Int, Multiplication](i))

  implicit val CharProductReducer: Reducer[Char, Char @@ Multiplication] = unitReducer(c => Tag[Char, Multiplication](c))

  implicit val ByteProductReducer: Reducer[Byte, Byte @@ Multiplication] = unitReducer(b => Tag[Byte, Multiplication](b))

  implicit val LongProductReducer: Reducer[Long, Long @@ Multiplication] = unitReducer(l => Tag[Long, Multiplication](l))

  implicit val ShortProductReducer: Reducer[Short, Short @@ Multiplication] = unitReducer(s => Tag[Short, Multiplication](s))


  implicit val BigIntProductReducer: Reducer[BigInt, BigInt @@ Multiplication] = {
    import std.math.bigInt._
    unitReducer(b => Tag[BigInt, Multiplication](b))
  }

  import std.option._

  implicit def FirstReducer[A]: Reducer[A, Option[A] @@ First] = unitReducer(a => Tag[Option[A], First](Some(a)))

  implicit def FirstOptionReducer[A]: Reducer[Option[A], Option[A] @@ First] = unitReducer(o => Tag[Option[A], First](o))

  implicit def LastReducer[A]: Reducer[A, Option[A] @@ Last] = unitReducer(a => Tag[Option[A], Last](Some(a)))

  implicit def LastOptionReducer[A]: Reducer[Option[A], Option[A] @@ Last] = unitReducer(o => Tag[Option[A], Last](o))

  /** Alias for [[scalaz.Reducer]]`.apply`. */
  def reducer[C, M](u: C => M, cs: C => M => M, sc: M => C => M)(implicit mm: Monoid[M]): Reducer[C, M] =
    new Reducer[C, M] {
      val monoid = mm

      def unit(c: C) = u(c)

      def snoc(m: M, c: C): M = sc(m)(c)

      def cons(c: C, m: M): M = cs(c)(m)
    }

  def foldReduce[F[_], A, B](a: F[A])(implicit f: Foldable[F], r: Reducer[A, B]): B =
    f.foldMap(a)(r.unit(_))(r.monoid)

  /** Alias for [[scalaz.UnitReducer]]`.apply`. */
  def unitReducer[C, M](u: C => M)(implicit mm: Monoid[M]): Reducer[C, M] =
    new UnitReducer[C, M] {
      val monoid = mm
      def unit(c: C) = u(c)
    }

  def unitConsReducer[C, M](u: C => M, cs: C => M => M)(implicit mm: Monoid[M]): Reducer[C, M] = new Reducer[C, M] {
    val monoid = mm

    def unit(c: C) = u(c)

    def snoc(m: M, c: C): M = mm.append(m, u(c))

    def cons(c: C, m: M): M = cs(c)(m)
  }

  /** The reducer derived from any monoid.  Not implicit because it is
    * suboptimal for most reducer applications.
    */
  def identityReducer[M](implicit mm: Monoid[M]): Reducer[M, M] = unitReducer(x => x)
}

Other Scala examples (source code examples)

Here is a short list of links related to this Scala Reducer.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.