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

quasar.physical.mongodb.accumulator.accumop.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014–2017 SlamData Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package quasar.physical.mongodb.accumulator

import slamdata.Predef._
import quasar.{RenderTree, Terminal}
import quasar.fp.ski._
import quasar.physical.mongodb.expression.ExprOpOps

import matryoshka._
import matryoshka.data.Fix
import scalaz._, Scalaz._

sealed abstract class AccumOp[A]

object AccumOp {
  final case class $addToSet[A](value: A) extends AccumOp[A]
  final case class $push[A](value: A)     extends AccumOp[A]
  final case class $first[A](value: A)    extends AccumOp[A]
  final case class $last[A](value: A)     extends AccumOp[A]
  final case class $max[A](value: A)      extends AccumOp[A]
  final case class $min[A](value: A)      extends AccumOp[A]
  final case class $avg[A](value: A)      extends AccumOp[A]
  final case class $sum[A](value: A)      extends AccumOp[A]

  implicit val instance: Traverse1[AccumOp] with Comonad[AccumOp]  =
    new Traverse1[AccumOp] with Comonad[AccumOp] {
      def cobind[A, B](fa: AccumOp[A])(f: (AccumOp[A]) ⇒ B) = map(fa)(κ(f(fa)))

      def copoint[A](p: AccumOp[A]) =
        p match {
          case $addToSet(value) => value
          case $avg(value)      => value
          case $first(value)    => value
          case $last(value)     => value
          case $max(value)      => value
          case $min(value)      => value
          case $push(value)     => value
          case $sum(value)      => value
        }

      def foldMapRight1[A, B](fa: AccumOp[A])(z: (A) ⇒ B)(f: (A, ⇒ B) ⇒ B) =
        z(copoint(fa))

      def traverse1Impl[G[_], A, B](fa: AccumOp[A])(f: A => G[B])(implicit G: Apply[G]) =
        fa match {
          case $addToSet(value) => G.map(f(value))($addToSet(_))
          case $avg(value)      => G.map(f(value))($avg(_))
          case $first(value)    => G.map(f(value))($first(_))
          case $last(value)     => G.map(f(value))($last(_))
          case $max(value)      => G.map(f(value))($max(_))
          case $min(value)      => G.map(f(value))($min(_))
          case $push(value)     => G.map(f(value))($push(_))
          case $sum(value)      => G.map(f(value))($sum(_))
        }
    }

  implicit def equal[A: Equal]: Equal[AccumOp[A]] = new Equal[AccumOp[A]] {

    def equal(left: AccumOp[A], right: AccumOp[A]) = (left, right) match {
      case ($addToSet(lv), $addToSet(rv)) => lv === rv
      case ($push(lv), $push(rv)) => lv === rv
      case ($first(lv), $first(rv)) => lv === rv
      case ($last(lv), $last(rv)) => lv === rv
      case ($max(lv), $max(rv)) => lv === rv
      case ($min(lv), $min(rv)) => lv === rv
      case ($avg(lv), $avg(rv)) => lv === rv
      case ($sum(lv), $sum(rv)) => lv === rv
      case _ => false
    }

    override def equalIsNatural = Equal[A].equalIsNatural
  }

  implicit val show: Delay[Show, AccumOp] = new Delay[Show, AccumOp] {
    def apply[A](s: Show[A]) = Show.show {
      case $addToSet(v) => Cord("$addToSet(") ++ s.show(v) ++ Cord(")")
      case $avg(v) => Cord("$avg(") ++ s.show(v) ++ Cord(")")
      case $first(v) => Cord("$first(") ++ s.show(v) ++ Cord(")")
      case $last(v) => Cord("$last(") ++ s.show(v) ++ Cord(")")
      case $max(v) => Cord("$max(") ++ s.show(v) ++ Cord(")")
      case $min(v) => Cord("$min(") ++ s.show(v) ++ Cord(")")
      case $push(v) => Cord("$push(") ++ s.show(v) ++ Cord(")")
      case $sum(v) => Cord("$sum(") ++ s.show(v) ++ Cord(")")
    }
  }

  implicit def renderTree[EX[_]: Functor](implicit exprOps: ExprOpOps.Uni[EX])
      : RenderTree[AccumOp[Fix[EX]]] =
    new RenderTree[AccumOp[Fix[EX]]] {
      def render(v: AccumOp[Fix[EX]]) =
        Terminal(List("AccumOp"), groupBson(v).toJs.pprint(0).some)
    }
}

object $addToSet {
  def apply[A](value: A): AccumOp[A] = AccumOp.$addToSet[A](value)
  def unapply[A](obj: AccumOp[A]): Option[A] = obj match {
    case AccumOp.$addToSet(value) => Some(value)
    case _                      => None
  }
}
object $push {
  def apply[A](value: A): AccumOp[A] = AccumOp.$push[A](value)
  def unapply[A](obj: AccumOp[A]): Option[A] = obj match {
    case AccumOp.$push(value) => Some(value)
    case _                  => None
  }
}
object $first {
  def apply[A](value: A): AccumOp[A] = AccumOp.$first[A](value)
  def unapply[A](obj: AccumOp[A]): Option[A] = obj match {
    case AccumOp.$first(value) => Some(value)
    case _                   => None
  }
}
object $last {
  def apply[A](value: A): AccumOp[A] = AccumOp.$last[A](value)
  def unapply[A](obj: AccumOp[A]): Option[A] = obj match {
    case AccumOp.$last(value) => Some(value)
    case _                  => None
  }
}
object $max {
  def apply[A](value: A): AccumOp[A] = AccumOp.$max[A](value)
  def unapply[A](obj: AccumOp[A]): Option[A] = obj match {
    case AccumOp.$max(value) => Some(value)
    case _                 => None
  }
}
object $min {
  def apply[A](value: A): AccumOp[A] = AccumOp.$min[A](value)
  def unapply[A](obj: AccumOp[A]): Option[A] = obj match {
    case AccumOp.$min(value) => Some(value)
    case _                 => None
  }
}
object $avg {
  def apply[A](value: A): AccumOp[A] = AccumOp.$avg[A](value)
  def unapply[A](obj: AccumOp[A]): Option[A] = obj match {
    case AccumOp.$avg(value) => Some(value)
    case _                 => None
  }
}
object $sum {
  def apply[A](value: A): AccumOp[A] = AccumOp.$sum[A](value)
  def unapply[A](obj: AccumOp[A]): Option[A] = obj match {
    case AccumOp.$sum(value) => Some(value)
    case _          => None
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy