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

shapeless.ops.adjoin.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2014 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 ops

import coproduct.ExtendBy
import hlist.Prepend

object adjoin {
  /**
   * Type class supporting the "flattening" of either an `HList` or `Coproduct` in such a way that
   * `HList` (or `Coproduct`, in the `Coproduct` case) elements are flattened.
   *
   * @author Travis Brown
   */
  trait Adjoin[A] extends DepFn1[A] with Serializable

  trait LowPriorityAdjoin {
    type Aux[A, Out0] = Adjoin[A] { type Out = Out0 }

    implicit def hlistAdjoin0[H, T <: HList](implicit
      adjoinT: Adjoin[T] { type Out <: HList }
    ): Aux[H :: T, H :: adjoinT.Out] =
      new Adjoin[H :: T] {
        type Out = H :: adjoinT.Out

        def apply(a: H :: T): H :: adjoinT.Out = a.head :: adjoinT(a.tail)
      }

    implicit def coproductAdjoin0[H, T <: Coproduct](
      implicit adjoinT: Adjoin[T] { type Out <: Coproduct }
    ): Aux[H :+: T, H :+: adjoinT.Out] =
      new Adjoin[H :+: T] {
        type Out = H :+: adjoinT.Out

        def apply(a: H :+: T): H :+: adjoinT.Out = a match {
          case Inl(h) => Inl(h)
          case Inr(t) => Inr(adjoinT(t))
        }
      }
  }

  object Adjoin extends LowPriorityAdjoin {
    def apply[A](implicit adjoin: Adjoin[A]): Aux[A, adjoin.Out] = adjoin

    implicit def hnilAdjoin: Aux[HNil, HNil] = new Adjoin[HNil] {
      type Out = HNil

      def apply(a: HNil): HNil = a
    }

    implicit def cnilAdjoin: Aux[CNil, CNil] = new Adjoin[CNil] {
      type Out = CNil

      def apply(a: CNil): CNil = a
    }

    implicit def hlistLAdjoin1[H <: HList, T <: HList, OutT <: HList](implicit
      adjoinT: Aux[T, OutT],
      prepend: Prepend[H, OutT]
    ): Aux[H :: T, prepend.Out] =
      new Adjoin[H :: T] {
        type Out = prepend.Out

        def apply(a: H :: T): prepend.Out = prepend(a.head, adjoinT(a.tail))
      }

    implicit def coproductAdjoin1[H <: Coproduct, T <: Coproduct, OutT <: Coproduct](implicit
      adjoinT: Aux[T, OutT],
      extend: ExtendBy[H, OutT]
    ): Aux[H :+: T, extend.Out] =
      new Adjoin[H :+: T] {
        type Out = extend.Out

        def apply(a: H :+: T): extend.Out = a match {
          case Inl(h) => extend.right(h)
          case Inr(t) => extend.left(adjoinT(t))
        }
      }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy