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

scaloi.syntax.CollectionBoxOps.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2007 Learning Objects
 *
 * 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 scaloi.syntax

import java.{lang => jl}

import scaloi.misc.{Boxes, JavaBuilders}
import scaloi.misc.JavaOptionalInstances

import scala.collection.Factory
import scalaz.Functor
import scalaz.std.OptionInstances

/** A collection of extension methods for dealing with collections of numeric types. */
object CollectionBoxOps extends ToCollectionBoxOps with OptionInstances

/** @tparam Coll the containing collection type
  * @tparam Elem the boxed object type
  */
final class BoxedCollectionOps[Coll[T], Elem](private val self: Coll[Elem]) extends AnyVal {

  /**
    * Convert the members of a collection from boxed to unboxed representation.
    *
    * Use as:
    * Seq[jl.Long](new jl.Long(1L)).unboxInside() : Seq[Long] = Seq(1L)
    *
    */
  def unboxInside: CollectionUnboxer[Coll, Elem, Coll] =
    new CollectionUnboxer[Coll, Elem, Coll](self)

  /**
    * Convert the members of a collection from boxed to unboxed representation,
    * while also changing the collection type.
    *
    * Use as:
    * Seq[jl.Long](new jl.Long(1L)).unboxInsideTo[List]() : List[Long] = List(1L)
    *
    */
  def unboxInsideTo[Out[_]]: CollectionUnboxer[Coll, Elem, Out] =
    new CollectionUnboxer[Coll, Elem, Out](self)
}

final class CollectionUnboxer[Coll[T], Elem, Out[_]](private val self: Coll[Elem]) extends AnyVal {
  def apply[UnboxedElem <: AnyVal]()(
    implicit boxes: Boxes[UnboxedElem, Elem],
    ap: CBOApplicable[Coll, Out, Elem, UnboxedElem]
  ): Out[UnboxedElem] =
    ap.map(self)(boxes.unbox)
}

/** @tparam Coll the containing collection type
  * @tparam Elem the unboxed primitive type
  */
final class UnboxedCollectionOps[Coll[T], Elem <: AnyVal](private val self: Coll[Elem]) extends AnyVal {

  /**
    * Convert the members of a collection from unboxed to boxed representation.
    *
    * Use as:
    * Seq[Long](1L).boxInside() : Seq[jl.Long] = Seq(1L)
    *
    */
  def boxInside: CollectionBoxer[Coll, Elem, Coll] =
    new CollectionBoxer[Coll, Elem, Coll](self)

  /**
    * Convert the members of a collection from unboxed to boxed representation,
    * while also changing the collection type.
    *
    * Use as:
    * Seq[Long](1L).boxInsideTo[List]() : List[jl.Long] = List(1L)
    *
    */
  def boxInsideTo[Out[_]]: CollectionBoxer[Coll, Elem, Out] =
    new CollectionBoxer[Coll, Elem, Out](self)
}

final class CollectionBoxer[Coll[T], Elem <: AnyVal, Out[_]](private val self: Coll[Elem]) extends AnyVal {
  def apply[BoxedElem]()(
    implicit boxes: Boxes[Elem, BoxedElem],
    ap: CBOApplicable[Coll, Out, Elem, BoxedElem]
  ): Out[BoxedElem] =
    ap.map(self)(boxes.box)
}

trait ToCollectionBoxOps extends JavaBuilders with JavaOptionalInstances {

  import language.implicitConversions

  implicit def toBoxedCollectionOps[Elem, CollIn[T]](self: CollIn[Elem]): BoxedCollectionOps[CollIn, Elem] =
    new BoxedCollectionOps[CollIn, Elem](self)

  implicit def toUnboxedCollectionOps[Elem <: AnyVal, CollIn[T]](
    self: CollIn[Elem]
  ): UnboxedCollectionOps[CollIn, Elem] =
    new UnboxedCollectionOps[CollIn, Elem](self)
}

trait CBOApplicable[CollIn[_], CollOut[_], ElemIn, ElemOut] {
  def map(ci: CollIn[ElemIn])(f: ElemIn => ElemOut): CollOut[ElemOut]
}

//noinspection ConvertExpressionToSAM
object CBOApplicable extends CBOApplicable0 {
  implicit def apFunctor[F[_], ElemIn, ElemOut](implicit F: Functor[F]): CBOApplicable[F, F, ElemIn, ElemOut] =
    new CBOApplicable[F, F, ElemIn, ElemOut] {
      def map(ci: F[ElemIn])(f: (ElemIn) => ElemOut): F[ElemOut] =
        F.map(ci)(f)
    }

  implicit def mkApGenTrav[CollIn[_], CollOut[_], ElemIn, ElemOut](
    implicit T: CollIn[ElemIn] <:< IterableOnce[ElemIn],
    fac: Factory[ElemOut, CollOut[ElemOut]]
  ): CBOApplicable[CollIn, CollOut, ElemIn, ElemOut] =
    new CBOApplicable[CollIn, CollOut, ElemIn, ElemOut] {
      def map(ci: CollIn[ElemIn])(f: (ElemIn) => ElemOut): CollOut[ElemOut] =
        ci.iterator.map(f).to(fac)
    }

  implicit def mkApJIterable[CollIn[_], CollOut[_], ElemIn, ElemOut](
    implicit T: CollIn[ElemIn] <:< jl.Iterable[ElemIn],
    fac: Factory[ElemOut, CollOut[ElemOut]]
  ): CBOApplicable[CollIn, CollOut, ElemIn, ElemOut] =
    new CBOApplicable[CollIn, CollOut, ElemIn, ElemOut] {

      import scala.jdk.CollectionConverters._

      def map(ci: CollIn[ElemIn])(f: (ElemIn) => ElemOut): CollOut[ElemOut] =
        ci.iterator.asScala.map(f).to(fac)
    }
}

sealed abstract class CBOApplicable0 {
  implicit def mkApOptional2ApplicativePlus[OptIn[_], APOut[_], ElemIn, ElemOut](
    implicit Opt: scalaz.Optional[OptIn],
    AP: scalaz.ApplicativePlus[APOut]
  ): CBOApplicable[OptIn, APOut, ElemIn, ElemOut] =
    new CBOApplicable[OptIn, APOut, ElemIn, ElemOut] {
      def map(ci: OptIn[ElemIn])(f: (ElemIn) => ElemOut): APOut[ElemOut] =
        Opt.pextract(ci).fold((_: OptIn[Nothing]) => AP.empty[ElemOut], ei => AP.point(f(ei)))
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy