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

shapeless.syntax.coproduct.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

/**
 * Carrier for `Coproduct` operations.
 *
 * These methods are implemented here and extended onto the minimal `Coproduct` types to avoid issues that would
 * otherwise be caused by the covariance of `:+:[H, T]`.
 *
 * @author Miles Sabin
 */
final class CoproductOps[C <: Coproduct](val c: C) extends AnyVal with Serializable {
  import ops.adjoin.Adjoin
  import ops.coproduct._

  /**
   * Returns the head of this `Coproduct`
   */
  def head(implicit cc: IsCCons[C]): Option[cc.H] = cc.head(c)

  /**
   * Returns the tail of this `Coproduct`
   */

  def tail(implicit cc: IsCCons[C]): Option[cc.T] = cc.tail(c)

  /**
   * Returns the ''nth'' element of this `Coproduct`. An explicit type must be provided.
   * Available only if there is evidence that this `Coproduct` has at least ''n'' elements.
   */
  def at[N <: Nat](implicit at: At[C, N]): Option[at.A] = at(c)

  /**
   * Returns the ''nth'' element of this `Coproduct`.
   * Available only if there is evidence that this `Coproduct` has at least ''n'' elements.
   */
  def at(n: Nat)(implicit at: At[C, n.N]): Option[at.A] = at(c)

  /**
   * Returns the last element of this 'Coproduct'
   */
  def last(implicit il: InitLast[C]): Option[il.L] = il.last(c)

  /**
   * Returns all elements except the last
   */
  def init(implicit il: InitLast[C]): Option[il.I] = il.init(c)

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

  /**
   * Returns all elements of type `U` of this `Coproduct`. An explicit type argument must be provided.
   */
  def filter[U](implicit partition: Partition[C, U]): Option[partition.Prefix]  = partition.filter(c)

  /**
   * Returns all elements of type different than `U` of this `Coproduct`. An explicit type argument must be provided.
   */
  def filterNot[U](implicit partition: Partition[C, U]): Option[partition.Suffix] = partition.filterNot(c)

  def partition[U](implicit partition: Partition[C, U]): Either[partition.Prefix, partition.Suffix] = partition(c)

  def partitionC[U]
    (implicit partition: Partition[C, U]): partition.Prefix :+: partition.Suffix :+: CNil = partition.coproduct(c)

  /**
   * Returns the first element of type `U` of this `Coproduct` plus the remainder of the `Coproduct`.
   * An explicit type argument must be provided. Available only if there is evidence that this
   * `Coproduct` has an element of type `U`.
   */
  def removeElem[U](implicit remove: Remove[C, U]): Either[U, remove.Rest] = remove(c)

  /**
   * Returns the first element of type `U` of this `Coproduct` plus the remainder of the `Coproduct`.
   * An explicit type argument must be provided. Available only if there is evidence that this
   * `Coproduct` has an element of type `U`.
   */
  def removeElemC[U](implicit remove: Remove[C, U]): U :+: remove.Rest = remove.coproduct(c)


  /**
   * Splits this `Coproduct` 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 `Coproduct` has at least ''n'' elements.
   */
  def split[N <: Nat](implicit split: Split[C, N]): split.Out = split(c)
  def splitC[N <: Nat](implicit split: Split[C, N]): split.Left :+: split.Right :+: CNil = split.coproduct(c)

  /**
   * Splits this `Coproduct` at the ''nth'' element, returning the prefix and suffix as a pair. Available only if
   * there is evidence that this `Coproduct` has at least ''n'' elements.
   */
  def split(n: Nat)(implicit split: Split[C, n.N]): split.Out = split(c)
  def splitC(n: Nat)(implicit split: Split[C, n.N]): split.Left :+: split.Right :+: CNil = split.coproduct(c)


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

  /**
   * Takes the first `n` elements of this `Coproduct`. Available only if
   * there is evidence that this `Coproduct` has at least ''n'' elements.
   */
  def take(n: Nat)(implicit take: Take[C, n.N]): take.Out = take(c)
  
  /**
   * Drops the first `n` elements of this `Coproduct`. An explicit type argument must be provided. Available only if
   * there is evidence that this `Coproduct` has at least ''n'' elements.
   */
  def drop[N <: Nat](implicit drop: Drop[C, N]): drop.Out = drop(c)

  /**
   * Drops the first `n` elements of this `Coproduct`. Available only if
   * there is evidence that this `Coproduct` has at least ''n'' elements.
   */
  def drop(n: Nat)(implicit drop: Drop[C, n.N]): drop.Out = drop(c)

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

  /**
   * Permutes this `Coproduct` into the same order as another `Coproduct`. Available only if 
   * both `Coproduct`s have elements of the same types.
   */
  def align[K <: Coproduct](k: K)(implicit align: Align[C, K]): K = align(c)

  /**
   * Reverses this `Coproduct`.
   */
  def reverse(implicit reverse: Reverse[C]): reverse.Out = reverse(c)

  /**
   * Maps a higher rank function across this `Coproduct`.
   */
  def map(f: Poly)(implicit mapper: Mapper[f.type, C]): mapper.Out = mapper(c)

  /**
   * Flatmaps a higher rank function across this `Coproduct`.
   */
  def flatMap(op: Poly)(implicit flatMap: FlatMap[C, op.type]): flatMap.Out = flatMap(c)

  /**
   * Computes a fold over this `Coproduct` using the higher ranked function `f`. Available only if
   * there is evidence `f` can be applied all the elements of this `Coproduct`.
   */
  def fold(f: Poly)(implicit folder: Folder[f.type, C]): folder.Out = folder(c)

  /**
   * Computes a left fold over this `Coproduct` using the polymorphic binary combining operator `op`.
   */
  def foldLeft[In](z: In)(op: Poly)(implicit folder: LeftFolder[C, In, op.type]): folder.Out = folder(c, z)

  /**
   * Returns the value of this `Coproduct`, typed as the least upper bound of this `Coproduct` elements' types
   */
  def unify(implicit unifier: Unifier[C]): unifier.Out = unifier(c)

  /**
   * Compute the length of this `Coproduct`.
   */
  def length(implicit length: Length[C]): length.Out = length()

  /**
   * Zips this `Coproduct` with the given constant, resulting in a `Coproduct` of tuples of the form
   * ({element from this `Coproduct`}, {supplied constant})
   */
  def zipConst[Z](z: Z)(implicit zipConst: ZipConst[Z, C]): zipConst.Out = zipConst(z, c)

  /**
   * Converts this `Coproduct` of values into a union with the provided keys.
   */
  def zipWithKeys[K <: HList](keys: K)(implicit zipWithKeys: ZipWithKeys[K, C]): zipWithKeys.Out = zipWithKeys(c)

  /**
   * Converts this `Coproduct` of values into a union with given keys. A type argument must be provided.
   */
  def zipWithKeys[K <: HList](implicit zipWithKeys: ZipWithKeys[K, C]): zipWithKeys.Out = zipWithKeys(c)
  
  /**
   * Zips this `Coproduct` with its element indices, resulting in a `Coproduct` of tuples of the form
   * ({element from input tuple}, {element index})
   */
  def zipWithIndex(implicit zipper: ZipWithIndex[C]): zipper.Out = zipper(c)

  /**
   * Zips this `Coproduct` with the provided `HList`, resulting in a `Coproduct` of tuples of the form
   * ({element from this `Coproduct`}, {element from input `HList`}). 
   */
  def zipWith[H <: HList](h: H)(implicit zipWith: ZipWith[H, C]): zipWith.Out = zipWith(h, c)

  /**
   * Rotate this 'Coproduct' left by N. An explicit type argument must be provided.
   */
  def rotateLeft[N <: Nat](implicit rotateLeft: RotateLeft[C, N]): rotateLeft.Out = rotateLeft(c)

  /**
   * Rotate this 'Coproduct' left by `n`
   */
  def rotateLeft(n: Nat)(implicit rotateLeft: RotateLeft[C, n.N]): rotateLeft.Out = rotateLeft(c)

  /**
   * Rotate this 'Coproduct' right by N. An explicit type argument must be provided.
   */
  def rotateRight[N <: Nat](implicit rotateRight: RotateRight[C, N]): rotateRight.Out = rotateRight(c)

  /**
   * Rotate this 'Coproduct' right by `n`
   */
  def rotateRight(n: Nat)(implicit rotateRight: RotateRight[C, n.N]): rotateRight.Out = rotateRight(c)

  /**
   * Extend this `Coproduct` on the left.
   */
  def extendLeft[T]: T :+: C = Inr[T, C](c)

  /**
   * Extend this `Coproduct` on the right.
   */
  def extendRight[T](implicit extendRight: ExtendRight[C, T]): extendRight.Out = extendRight(c)

  /**
   * Extend this `Coproduct` on the left.
   */
  def extendLeftBy[K <: Coproduct](implicit extendLeftBy: ExtendLeftBy[K, C]): extendLeftBy.Out =
    extendLeftBy(c)

  /**
   * Extend this `Coproduct` on the right.
   */
  def extendRightBy[K <: Coproduct](implicit extendRightBy: ExtendRightBy[C, K]): extendRightBy.Out =
    extendRightBy(c)

  /**
   * Embeds this `Coproduct` into a "bigger" `Coproduct` if possible.
   *
   * For instance, `Int :+: String :+: CNil` can be embedded in `Int :+: Bool :+: String :+: CNil`.
   */
  def embed[Super <: Coproduct](implicit basis: Basis[Super, C]): Super =
    basis.inverse(Right(c))

  /**
   * De-embeds a sub-`Coproduct` from this `Coproduct` if possible.
   */
  def deembed[Sub <: Coproduct](implicit basis: Basis[C, Sub]): basis.Out =
    basis(c)

  /**
   * Adjoins the elements of this `Coproduct` by flattening any `Coproduct` elements.
   */
  def adjoined(implicit adjoin: Adjoin[C]): adjoin.Out = adjoin(c)

  /**
   *  Embeds this `Coproduct` into an `Either`
   */
  def toEither(implicit coproductToEither: CoproductToEither[C]): coproductToEither.Out = coproductToEither(c)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy