All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kits.Monoid.scala Maven / Gradle / Ivy

The newest version!
package kits

trait Monoid[A] extends Any { A =>
  def empty: A
  def append(x: A, y: A): A
  def applicative = new Applicative[({ type F[B] = A })#F] {
    def pure[B](b: B): A = A.empty
    def apply[B, C](fb: A)(f: A): A = A.append(f, fb)
  }
}

object Monoid {
  def append[A](xs: A*)(implicit A: Monoid[A]): A = xs.foldLeft(A.empty)(A.append)
  def multiply[A: Monoid](a: A, n: Int): A = append(Seq.fill(n)(a): _*)
  implicit def sum[A](implicit A: Numeric[A]) = new Monoid[A] {
    def empty: A = A.zero
    def append(x: A, y: A): A = A.plus(x, y)
  }
  implicit def product[A](implicit A: Numeric[A]) = new Monoid[A] {
    def empty: A = A.one
    def append(x: A, y: A): A = A.times(x, y)
  }
  implicit val all = new Monoid[Boolean] {
    def empty: Boolean = true
    def append(x: Boolean, y: Boolean): Boolean = x && y
  }
  implicit val any = new Monoid[Boolean] {
    def empty: Boolean = false
    def append(x: Boolean, y: Boolean): Boolean = x || y
  }
  implicit val string = new Monoid[String] {
    def empty: String = ""
    def append(x: String, y: String): String = x + y
  }
  implicit val unit = new Monoid[Unit] {
    def empty: Unit = ()
    def append(x: Unit, y: Unit): Unit = ()
  }
  implicit def list[A] = new Monoid[List[A]] {
    def empty: List[A] = Nil
    def append(x: List[A], y: List[A]): List[A] = x ::: y
  }
  implicit def vector[A] = new Monoid[Vector[A]] {
    def empty: Vector[A] = Vector.empty
    def append(x: Vector[A], y: Vector[A]): Vector[A] = x ++ y
  }
  implicit def option[A](implicit A: Monoid[A]) = new Monoid[Option[A]] {
    def empty: Option[A] = None
    def append(x: Option[A], y: Option[A]): Option[A] =
      (x, y) match {
        case (None, None) => None
        case (_, None) => x
        case (None, _) => y
        case (Some(a), Some(b)) => Some(A.append(a, b))
      }
  }
  implicit def first[A] = new Monoid[Option[A]] {
    def empty: Option[A] = None
    def append(x: Option[A], y: Option[A]): Option[A] = x.orElse(y)
  }
  implicit def last[A] = new Monoid[Option[A]] {
    def empty: Option[A] = None
    def append(x: Option[A], y: Option[A]): Option[A] = y.orElse(x)
  }
  implicit def map[K, V](implicit V: Monoid[V]) = new Monoid[Map[K, V]] {
    def empty: Map[K, V] = Map.empty
    def append(x: Map[K, V], y: Map[K, V]): Map[K, V] =
      x.foldLeft(y) {
        case (a, (k, v)) => a.updated(k, a.get(k).fold(v)(V.append(v, _)))
      }
  }
  implicit def set[A] = new Monoid[Set[A]] {
    def empty: Set[A] = Set.empty
    def append(x: Set[A], y: Set[A]): Set[A] = x | y
  }
  implicit def endo[A] = new Monoid[A => A] {
    def empty: A => A = identity
    def append(f: A => A, g: A => A): A => A = f.andThen(g)
  }
  implicit def pair[A, B](implicit A: Monoid[A], B: Monoid[B]) = new Monoid[(A, B)] {
    def empty: (A, B) = (A.empty, B.empty)
    def append(x: (A, B), y: (A, B)): (A, B) = (A.append(x._1, y._1), B.append(x._2, y._2))
  }
  implicit def triple[A, B, C](implicit A: Monoid[A], B: Monoid[B], C: Monoid[C]) = new Monoid[(A, B, C)] {
    def empty: (A, B, C) = (A.empty, B.empty, C.empty)
    def append(x: (A, B, C), y: (A, B, C)): (A, B, C) = (A.append(x._1, y._1), B.append(x._2, y._2), C.append(x._3, y._3))
  }
  implicit def ordering[A] = new Monoid[Ordering[A]] {
    def empty = new Ordering[A] {
      def compare(a: A, b: A): Int = 0
    }
    def append(x: Ordering[A], y: Ordering[A]) = new Ordering[A] {
      def compare(a: A, b: A): Int =
        x.compare(a, b) match {
          case 0 => y.compare(a, b)
          case n => n
        }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy