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

shapeless.syntax.std.tuples.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2013-15 Miles Sabin 
 *
 * 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 shapeless
package syntax
package std

trait LowPriorityTuple {
  implicit def productTupleOps[P <: Product](p: P): TupleOps[P] = new TupleOps(p)
}

object tuple extends LowPriorityTuple {
  implicit def unitTupleOps(u: Unit): TupleOps[Unit] = new TupleOps(u)

  // Duplicated here from shapeless.HList so that explicit imports of tuple._ don't
  // clobber the conversion to HListOps.
  implicit def hlistOps[L <: HList](l : L) : HListOps[L] = new HListOps(l)
}

final class TupleOps[T](t: T) extends Serializable {
  import ops.tuple._

  /**
   * Returns an `HList` containing the elements of this tuple.
   */
  def productElements(implicit gen: Generic[T]): gen.Repr = gen.to(t)

  /**
   * Returns the first element of this tuple.
   */
  def head(implicit c: IsComposite[T]): c.H = c.head(t)

  /**
   * Returns that tail of this tuple. Available only if there is evidence that this tuple is composite.
   */
  def tail(implicit c: IsComposite[T]): c.T = c.tail(t)

  /**
   * Prepend the argument element to this tuple.
   */
  def +:[E](e: E)(implicit prepend: Prepend[Tuple1[E], T]): prepend.Out = prepend(Tuple1(e), t)

  /**
   * Append the argument element to this tuple.
   */
  def :+[E](e: E)(implicit prepend: Prepend[T, Tuple1[E]]): prepend.Out = prepend(t, Tuple1(e))

  /**
   * Append the argument tuple to this tuple.
   */
  def ++[U](u: U)(implicit prepend: Prepend[T, U]): prepend.Out = prepend(t, u)
  
  /**
   * Prepend the argument tuple to this tuple.
   */
  def ++:[U](u: U)(implicit prepend: Prepend[U, T]): prepend.Out = prepend(u, t)
  
  /**
   * Prepend the argument tuple to this tuple.
   */
  def :::[U](u: U)(implicit prepend: Prepend[U, T]): prepend.Out = prepend(u, t)

  /**
   * Prepend the reverse of the argument tuple to this tuple.
   */
  def reverse_:::[U](u: U)(implicit prepend: ReversePrepend[U, T]): prepend.Out = prepend(u, t)

  /**
   * Returns the ''nth'' element of this tuple. An explicit type argument must be provided. Available only if there is
   * evidence that this tuple has at least ''n'' elements.
   */
  def apply[N <: Nat](implicit at: At[T, N]): at.Out = at(t)

  /**
   * Returns the ''nth'' element of this tuple. Available only if there is evidence that this tuple has at least ''n''
   * elements.
   */
  def apply(n: Nat)(implicit at: At[T, n.N]): at.Out = at(t)
  
  /**
   * Returns the ''nth'' element of this tuple. An explicit type argument must be provided. Available only if there is
   * evidence that this tuple has at least ''n'' elements.
   */
  def at[N <: Nat](implicit at: At[T, N]): at.Out = at(t)

  /**
   * Returns the ''nth'' element of this tuple. Available only if there is evidence that this tuple has at least ''n''
   * elements.
   */
  def at(n: Nat)(implicit at: At[T, n.N]): at.Out = at(t)
  
  /**
   * Returns the last element of this tuple. Available only if there is evidence that this tuple is composite.
   */
  def last(implicit last: Last[T]): last.Out = last(t)

  /**
   * Returns a tuple consisting of all the elements of this tuple except the last. Available only if there is
   * evidence that this tuple is composite.
   */
  def init(implicit init: Init[T]): init.Out = init(t)

  /**
   * Returns the first element of type `U` of this tuple. An explicit type argument must be provided. Available only
   * if there is evidence that this tuple has an element of type `U`.
   */
  def select[U](implicit selector: Selector[T, U]): selector.Out = selector(t)

  /**
   * Returns all elements of type `U` of this tuple. An explicit type argument must be provided.
   */
  def filter[U](implicit filter: Filter[T, U]): filter.Out = filter(t)

  /**
   * Returns all elements of type different than `U` of this tuple. An explicit type argument must be provided.
   */
  def filterNot[U](implicit filterNot: FilterNot[T, U]): filterNot.Out = filterNot(t)
  
  /**
   * Returns the first element of type `U` of this tuple plus the remainder of the tuple. An explicit type argument
   * must be provided. Available only if there is evidence that this tuple has an element of type `U`.
   * 
   * The `Elem` suffix is here for consistency with the corresponding method name for `HList` and should be
   * removed when the latter is removed.
   */
  def removeElem[U](implicit remove: Remove[T, U]): remove.Out = remove(t)
  
  /**
   * Returns the first elements of this tuple that have types in `S` plus the remainder of the tuple. An expicit
   * type argument must be provided. Available only if there is evidence that this tuple contains elements with
   * types in `S`.
   */
  def removeAll[S](implicit removeAll: RemoveAll[T, S]): removeAll.Out = removeAll(t)

  /**
   * Replaces the first element of type `U` of this tuple with the supplied value, also of type `U` returning both
   * the replaced element and the updated tuple. Available only if there is evidence that this tuple has an element
   * of type `U`.
   */
  def replace[U](u: U)(implicit replacer: Replacer[T, U, U]): replacer.Out = replacer(t, u)
  
  class ReplaceTypeAux[U] {
    def apply[V](v: V)(implicit replacer: Replacer[T, V, U]): replacer.Out = replacer(t, v)
  }
  
  /**
   * Replaces the first element of type `U` of this tuple with the supplied value of type `V`, returning both the
   * replaced element and the updated tuple. An explicit type argument must be provided for `U`. Available only if
   * there is evidence that this tuple has an element of type `U`.
   */
  def replaceType[U] = new ReplaceTypeAux[U]
  
  /**
   * Replaces the first element of type `U` of this tuple with the supplied value, also of type `U`. Available only
   * if there is evidence that this tuple has an element of type `U`.
   * 
   * The `Elem` suffix is here for consistency with the corresponding method name for `HList` and should be
   * removed when the latter is removed.
   */
  def updatedElem[U, R](u: U)
    (implicit replacer: Replacer.Aux[T, U, U, (U, R)]): R = replacer(t, u)._2
  
  class UpdatedTypeAux[U] {
    def apply[V, R](v: V)(implicit replacer: Replacer.Aux[T, V, U, (U, R)]): R = replacer(t, v)._2
  }

  /**
   * Replaces the first element of type `U` of this tuple with the supplied value of type `V`. An explicit type
   * argument must be provided for `U`. Available only if there is evidence that this tuple has an element of
   * type `U`.
   */
  def updatedType[U] = new UpdatedTypeAux[U]

  class UpdateWithAux[U] {
    def apply[V, R](f: U => V)(implicit modifier: Modifier.Aux[T, U, V, (U, R)]): R = modifier(t, f)._2
  }

  /**
   * Replaces the first element of type `U` of this tuple with the result of its transformation to a `V` via the
   * supplied function. Available only if there is evidence that this tuple has an element of type `U`.
   */
  def updateWith[U] = new UpdateWithAux[U]

  /**
   * Replaces the `N`th element of this `Tuple` with the result of calling the supplied function on it.
   * Available only if there is evidence that this `Tuple` has `N` elements.
   *
   * @author Andreas Koestler
   */
  def updateAtWith[U](n: NatWith[({ type λ[t <: Nat] = At[T, t] })#λ])(f: n.instance.Out => U)
    (implicit upd: ModifierAt[T, n.N, n.instance.Out, U]): upd.Out = upd(t, f)

  class UpdatedAtAux[N <: Nat] {
    def apply[U, V, R](u: U)(implicit replacer: ReplaceAt.Aux[T, N, U, (V, R)]): R = replacer(t, u)._2
  }


  /**
   * Replaces the ''nth' element of this tuple with the supplied value of type `U`. An explicit type argument
   * must be provided for `N`. Available only if there is evidence that this tuple has at least ''n'' elements.
   */
  def updatedAt[N <: Nat] = new UpdatedAtAux[N]

  /**
   * Replaces the ''nth' element of this tuple with the supplied value of type `U`. Available only if there is
   * evidence that this tuple has at least ''n'' elements.
   */
  def updatedAt[U, V, R](n: Nat, u: U)(implicit replacer: ReplaceAt.Aux[T, n.N, U, (V, R)]): R = replacer(t, u)._2

  /**
   * Returns the first ''n'' elements of this tuple. An explicit type argument must be provided. Available only if
   * there is evidence that this tuple has at least ''n'' elements.
   */
  def take[N <: Nat](implicit take: Take[T, N]): take.Out = take(t)

  /**
   * Returns the first ''n'' elements of this tuple. Available only if there is evidence that this tuple has at
   * least ''n'' elements.
   */
  def take(n: Nat)(implicit take: Take[T, n.N]): take.Out = take(t)
  
  /**
   * Returns all but the  first ''n'' elements of this tuple. An explicit type argument must be provided. Available
   * only if there is evidence that this tuple has at least ''n'' elements.
   */
  def drop[N <: Nat](implicit drop: Drop[T, N]): drop.Out = drop(t)

  /**
   * Returns all but the  first ''n'' elements of this tuple. Available only if there is evidence that this tuple
   * has at least ''n'' elements.
   */
  def drop(n: Nat)(implicit drop: Drop[T, n.N]): drop.Out = drop(t)
  
  /**
   * Splits this tuple at the ''nth'' element, returning the prefix and suffix as a pair. An explicit type argument
   * must be provided. Available only if there is evidence that this tuple has at least ''n'' elements.
   */
  def split[N <: Nat](implicit split: Split[T, N]): split.Out = split(t)

  /**
   * Splits this tuple at the ''nth'' element, returning the prefix and suffix as a pair. Available only if there is
   * evidence that this tuple has at least ''n'' elements.
   */
  def split(n: Nat)(implicit split: Split[T, n.N]): split.Out = split(t)
  
  /**
   * Splits this tuple at the ''nth'' element, returning the reverse of the prefix and suffix as a pair. An explicit
   * type argument must be provided. Available only if there is evidence that this tuple has at least ''n'' elements.
   */
  def reverse_split[N <: Nat](implicit split: ReverseSplit[T, N]): split.Out = split(t)

  /**
   * Splits this tuple at the ''nth'' element, returning the reverse of the prefix and suffix as a pair. Available
   * only if there is evidence that this tuple has at least ''n'' elements.
   */
  def reverse_split(n: Nat)(implicit split: ReverseSplit[T, n.N]): split.Out = split(t)

  /**
   * Splits this tuple at the first occurrence of an element of type `U`, returning the prefix and suffix as a pair.
   * An explicit type argument must be provided. Available only if there is evidence that this tuple has an element
   * of type `U`.
   */
  def splitLeft[U](implicit splitLeft: SplitLeft[T, U]): splitLeft.Out = splitLeft(t)

  /**
   * Splits this tuple at the first occurrence of an element of type `U`, returning reverse of the prefix and suffix
   * as a pair. An explicit type argument must be provided. Available only if there is evidence that this tuple has
   * an element of type `U`.
   */
  def reverse_splitLeft[U](implicit splitLeft: ReverseSplitLeft[T, U]): splitLeft.Out = splitLeft(t)

  /**
   * Splits this tuple at the last occurrence of an element of type `U`, returning the prefix and suffix as a pair.
   * An explicit type argument must be provided. Available only if there is evidence that this tuple has an element
   * of type `U`.
   */
  def splitRight[U](implicit splitRight: SplitRight[T, U]): splitRight.Out = splitRight(t)

  /**
   * Splits this tuple at the last occurrence of an element of type `U`, returning reverse of the prefix and suffix
   * as a pair. An explicit type argument must be provided. Available only if there is evidence that this tuple has
   * an element of type `U`.
   */
  def reverse_splitRight[U](implicit splitRight: ReverseSplitRight[T, U]): splitRight.Out = splitRight(t)

  /**
   * Reverses this tuple.
   */
  def reverse(implicit reverse: Reverse[T]): reverse.Out = reverse(t)

  /**
   * Maps a higher rank function across this tuple.
   */
  def map(f: Poly)(implicit mapper: Mapper[T, f.type]): mapper.Out = mapper(t)

  /**
   * Flatmaps a higher rank function across this tuple.
   */
  def flatMap(f: Poly)(implicit mapper: FlatMapper[T, f.type]): mapper.Out = mapper(t)

  /**
   * Replaces each element of this tuple with a constant value.
   */
  def mapConst[C](c: C)(implicit mapper: ConstMapper[T, C]): mapper.Out = mapper(t, c)

  /**
   * Collect a higher rank function across this tuple
   */
  def collect(p: Poly)(implicit collect: Collect[T, p.type]): collect.Out = collect(t)

  /**
   * Maps a higher rank function ''f'' across this tuple and folds the result using monomorphic combining operator
   * `op`. Available only if there is evidence that the result type of `f` at each element conforms to the argument
   * type of ''op''.
   */
  def foldMap[R](z: R)(f: Poly)(op: (R, R) => R)(implicit folder: MapFolder[T, R, f.type]): R = folder(t, z, op)

  /**
   * Computes a left fold over this tuple using the polymorphic binary combining operator `op`. Available only if
   * there is evidence `op` can consume/produce all the partial results of the appropriate types.
   */
  def foldLeft[R](z: R)(op: Poly)(implicit folder: LeftFolder[T, R, op.type]): folder.Out = folder(t, z)
  
  /**
   * Computes a right fold over this tuple using the polymorphic binary combining operator `op`. Available only if
   * there is evidence `op` can consume/produce all the partial results of the appropriate types.
   */
  def foldRight[R](z: R)(op: Poly)(implicit folder: RightFolder[T, R, op.type]): folder.Out = folder(t, z)
  
  /**
   * Computes a left reduce over this tuple using the polymorphic binary combining operator `op`. Available only if
   * there is evidence that this tuple has at least one element and that `op` can consume/produce all the partial
   * results of the appropriate types.
   */
  def reduceLeft(op: Poly)(implicit reducer: LeftReducer[T, op.type]): reducer.Out = reducer(t)
  
  /**
   * Computes a right reduce over this tuple using the polymorphic binary combining operator `op`. Available only if
   * there is evidence that this tuple has at least one element and that `op` can consume/produce all the partial
   * results of the appropriate types.
   */
  def reduceRight(op: Poly)(implicit reducer: RightReducer[T, op.type]): reducer.Out = reducer(t)

  /**
   * Zips this tuple with its argument tuple returning a tuple of pairs.
   */
  def zip[R](r: R)(implicit transpose: Transposer[(T, R)]): transpose.Out = transpose((t, r))
  
  /**
   * Zips this tuple of monomorphic function values with its argument tuple of correspondingly typed function
   * arguments returning the result of each application as a tuple. Available only if there is evidence that the
   * corresponding function and argument elements have compatible types.
   */
  def zipApply[A](a: A)(implicit zipper: ZipApply[T, A]): zipper.Out = zipper(t, a)

  /**
   * Zips this tuple of tuples returning a tuple of tuples. Available only if there is evidence that this
   * tuple has tuple elements.
   */
  def zip(implicit transpose: Transposer[T]): transpose.Out = transpose(t)

  /**
   * Unzips this tuple of tuples returning a tuple of tuples. Available only if there is evidence that this
   * tuple has tuple elements.
   */
  def unzip(implicit transpose: Transposer[T]): transpose.Out = transpose(t)
  
  /**
   * Zips this tuple with its argument tuple of tuples, returning a tuple of tuples with each element of
   * this tuple prepended to the corresponding tuple element of the argument tuple.
   */
  def zipOne[R](r: R)(implicit zipOne: ZipOne[T, R]): zipOne.Out = zipOne(t, r)

  /**
   * Zips this tuple with a constant, resulting in a tuple of tuples, with each element being of the form
   * ({element from original tuple}, {supplied constant})
   */
  def zipConst[C](c: C)(implicit zipper: ZipConst[T, C]): zipper.Out = zipper(t, c)

  /**
   * Zips this tuple with its element indices, resulting in a tuple of tuples of the form
   * ({element from input tuple}, {element index})
   */
  def zipWithIndex(implicit zipper: ZipWithIndex[T]): zipper.Out = zipper(t)

  /**
   * Transposes this tuple.
   */
  def transpose(implicit transpose: Transposer[T]): transpose.Out = transpose(t)

  /**
   * Returns a tuple typed as a repetition of the least upper bound of the types of the elements of this tuple.
   */
  def unify(implicit unifier : Unifier[T]) : unifier.Out = unifier(t)

  /**
   * Returns a tuple with all elements that are subtypes of `B` typed as `B`.
   */
  def unifySubtypes[B](implicit subtypeUnifier : SubtypeUnifier[T, B]) : subtypeUnifier.Out = subtypeUnifier(t)
  
  /**
   * Compute the length of this tuple.
   */
  def length(implicit length : Length[T]) : length.Out = length(t)

  /**
   * Converts this tuple to a `M` of elements typed as the least upper bound of the types of the elements
   * of this tuple.
   */
  def to[M[_]](implicit toTraversable : ToTraversable[T, M]) : toTraversable.Out = toTraversable(t)

  /**
   * Converts this tuple to a `List` of elements typed as the least upper bound of the types of the elements
   * of this tuple.
   */
  def toList[Lub](implicit toTraversable : ToTraversable.Aux[T, List, Lub]) : toTraversable.Out = toTraversable(t)
  
  /**
   * Converts this tuple to an `Array` of elements typed as the least upper bound of the types of the elements
   * of this tuple.
   * 
   * It is advisable to specify the type parameter explicitly, because for many reference types, case classes in
   * particular, the inferred type will be too precise (ie. `Product with Serializable with CC` for a typical case class
   * `CC`) which interacts badly with the invariance of `Array`s.
   */
  def toArray[Lub](implicit toTraversable : ToTraversable.Aux[T, Array, Lub]) : toTraversable.Out = toTraversable(t)
  
  /**
   * Converts this tuple to a `M` of elements typed as the least upper bound of the types of the elements
   * of this tuple.
   */
  def toSized[M[_]](implicit toSized : ToSized[T, M]) : toSized.Out = toSized(t)

  /**
   * Returns all permutations of this tuple.
   */
  def permutations(implicit permutations: Permutations[T]): permutations.Out = permutations(t)

  /**
   * Displays all elements of this tuple in a string using start, end, and separator strings.
   */
  def mkString(start: String, sep: String, end: String)
    (implicit toTraversable: ToTraversable.Aux[T, List, Any]): String =
      this.toList.mkString(start, sep, end)

  /**
   * Rotate this tuple left by N
   */
  def rotateLeft(n: Nat)(implicit rotateLeft: RotateLeft[T, n.N]): rotateLeft.Out = rotateLeft(t)

  /**
   * Rotate this tuple right by N
   */
  def rotateRight(n: Nat)(implicit rotateRight: RotateRight[T, n.N]): rotateRight.Out = rotateRight(t)

  /**
   * Computes a left scan over this tuple using the polymorphic binary combining operator `op`. Available only if
   * there is evidence `op` can consume/produce all the results of the appropriate types.
   */
   def scanLeft[Z, P <: Poly](z: Z)(op: Poly)(implicit scanL: LeftScanner[T, Z, op.type]): scanL.Out = scanL(t, z)

   /**
   * Computes a left scan over this tuple using the polymorphic binary combining operator `op`. Available only if
   * there is evidence `op` can consume/produce all the results of the appropriate types.
   */
   def scanRight[Z, P <: Poly](z: Z)(op: Poly)(implicit scanR: RightScanner[T, Z, op.type]): scanR.Out = scanR(t, z)

  /**
   *
   * Produces a new tuple where a slice of this tuple is replaced by another. Available only if there are at least 
   * ``n`` plus ``m`` elements.
   */
  def patch[In](n: Nat, in: In, m: Nat)(implicit patcher: Patcher[n.N, m.N, T, In]): patcher.Out = patcher(t, in)

  /**
   * Produces a new tuple where a slice of this tuple is replaced by another. Two explicit type arguments must be provided.
   * Available only if there are at least `N` plus `M` elements.
   */
  def patch[N <: Nat, M <: Nat] = new PatchAux[N, M]

  class PatchAux[N <: Nat, M <: Nat]{
    def apply[In](in: In)(implicit patcher: Patcher[N, M, T, In]): patcher.Out = patcher(t, in)
  }

  /**
   * Groups the elements of this `Tuple` into tuples of `n` elements, offset by `step`
   *
   * @author Andreas Koestler
   */
  def group(n: Nat, step: Nat)(implicit grouper: Grouper[T, n.N, step.N]): grouper.Out = grouper(t)

  /**
   * Groups the elements of this `Tuple` into tuples of `n` elements, offset by `step`
   * Use elements in `pad` as necessary to complete last group up to `n` items.
   * @author Andreas Koestler
   */
  def group[Pad](n: Nat, step: Nat, pad: Pad)(implicit grouper: PaddedGrouper[T, n.N, step.N, Pad]): grouper.Out = grouper(t, pad)

  /**
   * Permutes this `Tuple` into the same order as another `Tuple`. An explicit type argument must be supplied.
   * Available only if both `Tuple`s have elements of the same types.
   */
  def align[U](implicit align: Align[T, U]): U = align(t)

  /**
   * Permutes this `Tuple` into the same order as the supplied `Tuple` with the same element types. Available only if
   * both `HList`s have elements of the same types.
   */
  def align[U](u: U)(implicit align: Align[T, U]): U = align(t)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy