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

scodec.HListOps.scala Maven / Gradle / Ivy

package scodec

import shapeless._
import shapeless.ops.hlist._

/** Operations on `HList`s that are not provided by Shapeless. */
object HListOps {

  /**
   * Computes the inverse of `(k: K).filterNot[Unit]` -- i.e., inserts unit values wherever the unit type
   * appears in `K`.
   * @tparam K type that may have `Unit` params
   * @tparam L equivalent to `K` with `Unit` params filtered out
   * @param l list to insert unit values in to
   * @return new list with unit values inserted
   */
  def reUnit[K <: HList, L <: HList](l: L)(implicit ru: ReUnit[K, L]): K = ru(l)

  /** Provides the `reUnit` method on an `HList`. */
  implicit class ReUnitSyntax[L <: HList](val l: L) extends AnyVal {
    def reUnit[K <: HList](implicit ru: ReUnit[K, L]): K = ru(l)
  }

  /** Typeclass that allows computation of the inverse of calling `filterNot[Unit]` on a `K`. */
  sealed trait ReUnit[K <: HList, L <: HList] {
    def apply(l: L): K
  }

  object ReUnit {
    implicit lazy val base: ReUnit[HNil, HNil] = new ReUnit[HNil, HNil] {
      def apply(l: HNil): HNil = HNil
    }

    implicit def `non-empty K and L where head of K and L are same type`[H, KT <: HList, LT <: HList](implicit
      reUnit: ReUnit[KT, LT],
      notUnit: H =:!= Unit
    ): ReUnit[H :: KT, H :: LT] = new ReUnit[H :: KT, H :: LT] {
      def apply(l: H :: LT): H :: KT =
         l.head :: reUnit(l.tail)
    }

    implicit def `non-empty K and any L where head of K is Unit`[KT <: HList, L <: HList](implicit
      reUnit: ReUnit[KT, L]
    ): ReUnit[Unit :: KT, L] = new ReUnit[Unit :: KT, L] {
      def apply(l: L): Unit :: KT =
         () :: reUnit(l)
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy