alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (Unapply.scala)

This example Scala source code file (Unapply.scala) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Scala by Example" TM.

Learn more about this Scala project at its project page.

Java - Scala tags/keywords

tc0, unapply

The Unapply.scala Scala example source code

package scalaz

import scala.annotation._
import Leibniz.{===, refl}

/**
 * Represents a type `MA` that has been destructured into as a type constructor `M[_]`
 * applied to type `A`, along with a corresponding type class instance `TC[M]`.
 *
 * The implicit conversions in the companion object provide a means to obtain type class
 * instances for partially applied type constructors, in lieu of direct compiler support
 * as described in [[https://issues.scala-lang.org/browse/SI-2712 SI-2712]].
 *
 * {{{
 * // Directly depending on Applicative[G]
 * def traverse[G[_], B](f: A => G[B])(implicit G: Applicative[G]): G[F[B]] =
 *   G.traverse(self)(f)
 *
 * // Indirect lookup of the Applicative instance
 * def traverseI[GB](f: A => GB)(implicit G: Unapply[Applicative, GB]): G.M[F[G.A]] /*G[F[B]*/ = {
 *   G.TC.traverse(self)(a => G(f(a)))
 * }
 *
 * // Deforested version of traverseI
 * def traverseI2[GB](f: A => GB)(implicit G: Unapply[Applicative, GB]): G.M[F[G.A]] /*G[F[B]*/ = {
 *   G.TC.traverse(self)(G.leibniz.onF(f))
 * }
 *
 * // Old usage
 * def stateTraverse1 {
 *   import scalaz._, Scalaz._
 *   import State.{State, stateMonad}
 *   val ls = List(1, 2, 3)
 *   val traverseOpt: Option[List[Int]] = ls.traverse(a => Some(a))
 *   val traverseState: State[Int, List[Int]] = ls.traverse[State[Int, ?], Int](a => State((x: Int) => (x + 1, a)))
 * }
 *
 * // New usage
 * def stateTraverse2 {
 *   import scalaz._, Scalaz._
 *   val ls = List(1, 2, 3)
 *   val traverseOpt: Option[List[Int]] = ls.traverseI(a => some(a))
 *   val traverseState = ls.traverseI(a => State((x: Int) => (x + 1, a)))
 * }
 *
 * }}}
 *
 * Credits to Miles Sabin.
 */
@implicitNotFound("Implicit not found: scalaz.Unapply[${TC}, ${MA}]. Unable to unapply type `${MA}` into a type constructor of kind `M[_]` that is classified by the type class `${TC}`. Check that the type class is defined by compiling `implicitly[${TC}[type constructor]]` and review the implicits in object Unapply, which only cover common type 'shapes.'")
trait Unapply[TC[_[_]], MA] {

  /** The type constructor */
  type M[_]

  /** The type that `M` was applied to */
  type A

  /** The instance of the type class */
  def TC: TC[M]

  /** Evidence that MA =:= M[A] */
  def leibniz: MA === M[A]

  /** Compatibility. */
  @inline final def apply(ma: MA): M[A] = leibniz(ma)
}

sealed abstract class Unapply_5 {
  /**Unpack a value of type `M0[F[_], A0, B0, C0, D0, E0]` into types `[e]M0[F, A0, B0, C0, D0, e]` and `E0`, given an instance of `TC` */
  implicit def unapplyMFABCDE5[TC[_[_]], F[_], M0[F[_], _, _, _, _, _], A0, B0, C0, D0, E0](implicit TC0: TC[M0[F, A0, B0, C0, D0, ?]]): Unapply[TC, M0[F, A0, B0, C0, D0, E0]] {
    type M[X] = M0[F, A0, B0, C0, D0, X]
    type A = E0
  } =
    new Unapply[TC, M0[F, A0, B0, C0, D0, E0]] {
      type M[X] = M0[F, A0, B0, C0, D0, X]
      type A = E0
      def TC = TC0
      def leibniz = refl
    }
}

sealed abstract class Unapply_4 extends Unapply_5 {
  // /** Unpack a value of type `A0` into type `[a]A0`, given a instance of `TC` */
  implicit def unapplyA[TC[_[_]], A0](implicit TC0: TC[λ[α => A0]]): Unapply[TC, A0] {
    type M[X] = A0
    type A = A0
  } =
    new Unapply[TC, A0] {
      type M[X] = A0
      type A = A0
      def TC = TC0
      def leibniz = refl
    }
}

sealed abstract class Unapply_3 extends Unapply_4 {
  /**Unpack a value of type `M0[F[_], A0, A0, B0]` into types `[a]M0[F, a, a, B0]` and `A0`, given an instance of `TC` */
  implicit def unapplyMFABC1and2[TC[_[_]], F[_], M0[F[_], _, _, _], A0, B0](implicit TC0: TC[λ[α => M0[F, α, α, B0]]]): Unapply[TC, M0[F, A0, A0, B0]] {
    type M[X] = M0[F, X, X, B0]
    type A = A0
  } =
    new Unapply[TC, M0[F, A0, A0, B0]] {
      type M[X] = M0[F, X, X, B0]
      type A = A0
      def TC = TC0
      def leibniz = refl
    }

  /**Unpack a value of type `M0[F[_], A0, B0, C0]` into types `[c]M0[F, A0, B0, c]` and `C0`, given an instance of `TC` */
  implicit def unapplyMFABC3[TC[_[_]], F[_], M0[F[_], _, _, _], A0, B0, C0](implicit TC0: TC[M0[F, A0, B0, ?]]): Unapply[TC, M0[F, A0, B0, C0]] {
    type M[X] = M0[F, A0, B0, X]
    type A = C0
  } =
    new Unapply[TC, M0[F, A0, B0, C0]] {
      type M[X] = M0[F, A0, B0, X]
      type A = C0
      def TC = TC0
      def leibniz = refl
    }
}

sealed abstract class Unapply_2 extends Unapply_3 {
  // Things get tricky with type State[S, A] = StateT[Id, S, A], both unapplyMAB2 and unapplyMFAB2 are applicable
  // Without characterizing this fully, I'm using the standard implicit prioritization to avoid this.

  /**Unpack a value of type `M0[F[_], A0, B0]` into types `[a]M0[F, a, B0]` and `A0`, given an instance of `TC` */
  implicit def unapplyMFAB1[TC[_[_]], F[_], M0[F[_], _, _], A0, B0](implicit TC0: TC[M0[F, ?, B0]]): Unapply[TC, M0[F, A0, B0]] {
    type M[X] = M0[F, X, B0]
    type A = A0
  } =
    new Unapply[TC, M0[F, A0, B0]] {
      type M[X] = M0[F, X, B0]
      type A = A0
      def TC = TC0
      def leibniz = refl
    }

  /**Unpack a value of type `M0[F[_], A0, B0]` into types `[b]M0[F, A0, b]` and `B0`, given an instance of `TC` */
  implicit def unapplyMFAB2[TC[_[_]], F[_], M0[F[_], _, _], A0, B0](implicit TC0: TC[M0[F, A0, ?]]): Unapply[TC, M0[F, A0, B0]] {
    type M[X] = M0[F, A0, X]
    type A = B0
  } =
    new Unapply[TC, M0[F, A0, B0]] {
      type M[X] = M0[F, A0, X]
      type A = B0
      def TC = TC0
      def leibniz = refl
    }
}

sealed abstract class Unapply_1 extends Unapply_2 {
  /**Unpack a value of type `M0[A0, B0, C0, D0, E0, F0, G0]` into types `[g]M0[A0, B0, C0, D0, E0, F0, g]` and `G0`, given an instance of `TC` */
  implicit def unapplyMABCDEFG7[TC[_[_]], M0[_, _, _, _, _, _, _], A0, B0, C0, D0, E0, F0, G0](implicit TC0: TC[M0[A0, B0, C0, D0, E0, F0, ?]]): Unapply[TC, M0[A0, B0, C0, D0, E0, F0, G0]] {
    type M[X] = M0[A0, B0, C0, D0, E0, F0, X]
    type A = G0
  } =
    new Unapply[TC, M0[A0, B0, C0, D0, E0, F0, G0]] {
      type M[X] = M0[A0, B0, C0, D0, E0, F0, X]
      type A = G0
      def TC = TC0
      def leibniz = refl
    }

  /**Unpack a value of type `M0[A0, B0, C0, D0, E0, F0]` into types `[f]M0[A0, B0, C0, D0, E0, f]` and `F0`, given an instance of `TC` */
  implicit def unapplyMABCDEF6[TC[_[_]], M0[_, _, _, _, _, _], A0, B0, C0, D0, E0, F0](implicit TC0: TC[M0[A0, B0, C0, D0, E0, ?]]): Unapply[TC, M0[A0, B0, C0, D0, E0, F0]] {
    type M[X] = M0[A0, B0, C0, D0, E0, X]
    type A = F0
  } =
    new Unapply[TC, M0[A0, B0, C0, D0, E0, F0]] {
      type M[X] = M0[A0, B0, C0, D0, E0, X]
      type A = F0
      def TC = TC0
      def leibniz = refl
    }

  /**Unpack a value of type `M0[A0, B0, C0, D0, E0]` into types `[e]M0[A0, B0, C0, D0, e]` and `E0`, given an instance of `TC` */
  implicit def unapplyMABCDE5[TC[_[_]], M0[_, _, _, _, _], A0, B0, C0, D0, E0](implicit TC0: TC[M0[A0, B0, C0, D0, ?]]): Unapply[TC, M0[A0, B0, C0, D0, E0]] {
    type M[X] = M0[A0, B0, C0, D0, X]
    type A = E0
  } =
    new Unapply[TC, M0[A0, B0, C0, D0, E0]] {
      type M[X] = M0[A0, B0, C0, D0, X]
      type A = E0
      def TC = TC0
      def leibniz = refl
    }

  /**Unpack a value of type `M0[A0, B0, C0, D0]` into types `[d]M0[A0, B0, C0, d]` and `D0`, given an instance of `TC` */
  implicit def unapplyMABCD4[TC[_[_]], M0[_, _, _, _], A0, B0, C0, D0](implicit TC0: TC[M0[A0, B0, C0, ?]]): Unapply[TC, M0[A0, B0, C0, D0]] {
    type M[X] = M0[A0, B0, C0, X]
    type A = D0
  } =
    new Unapply[TC, M0[A0, B0, C0, D0]] {
      type M[X] = M0[A0, B0, C0, X]
      type A = D0
      def TC = TC0
      def leibniz = refl
    }

  /**Unpack a value of type `M0[A0, B0, C0]` into types `[c]M0[A0, B0, c]` and `C0`, given an instance of `TC` */
  implicit def unapplyMABC3[TC[_[_]], M0[_, _, _], A0, B0, C0](implicit TC0: TC[M0[A0, B0, ?]]): Unapply[TC, M0[A0, B0, C0]] {
    type M[X] = M0[A0, B0, X]
    type A = C0
  } =
    new Unapply[TC, M0[A0, B0, C0]] {
      type M[X] = M0[A0, B0, X]
      type A = C0
      def TC = TC0
      def leibniz = refl
    }
}

sealed abstract class Unapply_0 extends Unapply_1 {
  /** Unpack a value of type `M0[F0, A0]` where `F0: * -> *` into
    * types `[a]M0[F0, a]` and `A`, given an instance of `TC`
    */
  implicit def unapplyMFA[TC[_[_]], M0[_[_], _], F0[_], A0](implicit TC0: TC[M0[F0, ?]]): Unapply[TC, M0[F0, A0]] {
    type M[X] = M0[F0, X]
    type A = A0
  } =
    new Unapply[TC, M0[F0, A0]] {
      type M[X] = M0[F0, X]
      type A = A0
      def TC = TC0
      def leibniz = refl
    }

  /**Unpack a value of type `M0[A0, B0]` into types `[a]M0[a, B0]` and `A`, given an instance of `TC` */
  implicit def unapplyMAB1[TC[_[_]], M0[_, _], A0, B0](implicit TC0: TC[M0[?, B0]]): Unapply[TC, M0[A0, B0]] {
    type M[X] = M0[X, B0]
    type A = A0
  } =
    new Unapply[TC, M0[A0, B0]] {
      type M[X] = M0[X, B0]
      type A = A0
      def TC = TC0
      def leibniz = refl
    }

  /**Unpack a value of type `M0[A0, B0]` into types `[b]M0[A0, b]` and `B`, given an instance of `TC` */
  implicit def unapplyMAB2[TC[_[_]], M0[_, _], A0, B0](implicit TC0: TC[M0[A0, ?]]): Unapply[TC, M0[A0, B0]] {
    type M[X] = M0[A0, X]
    type A = B0
  } =
    new Unapply[TC, M0[A0, B0]] {
      type M[X] = M0[A0, X]
      type A = B0
      def TC = TC0
      def leibniz = refl
    }
}

object Unapply extends Unapply_0 {
  type AuxA[TC[_[_]], MA, A0] = Unapply[TC, MA] {
    type A = A0
  }

  /** Fetch a well-typed `Unapply` for the given typeclass and type. */
  def apply[TC[_[_]], MA](implicit U: Unapply[TC, MA]): U.type {
    type M[A] = U.M[A]
    type A = U.A
  } = U

  /** Unpack a value of type `M0[A0]` into types `M0` and `A0`, given a instance of `TC` */
  implicit def unapplyMA[TC[_[_]], M0[_], A0](implicit TC0: TC[M0]): Unapply[TC, M0[A0]] {
    type M[X] = M0[X]
    type A = A0
  } =
    new Unapply[TC, M0[A0]] {
      type M[X] = M0[X]
      type A = A0
      def TC = TC0
      def leibniz = refl
    }

  /** Turns a MonadTrans-like instance that has two params and turns it into an M[A] */
  implicit def unapplyMTMAB[TC[_[_]], MT[_[_], _], MAB[_, _], A0, A1](implicit TC0: TC[MT[MAB[A0,?], ?]]):
    Unapply[TC, MT[MAB[A0, ?], A1]] {
      type M[X] = MT[MAB[A0, ?], X]
      type A = A1
    } = new Unapply[TC, MT[MAB[A0, ?], A1]] {
      type M[X] = MT[MAB[A0, ?], X]
      type A = A1
      def TC = TC0
      def leibniz = Leibniz.refl
    }
  // TODO More!
}

trait Unapply2[TC[_[_, _]], MAB] {

  /** The type constructor */
  type M[_, _]

  /** The first type that `M` was applied to */
  type A

  /** The second type that `M` was applied to */
  type B

  /** The instance of the type class */
  def TC: TC[M]

  /** Evidence that MAB =:= M[A, B] */
  def leibniz: MAB === M[A, B]

  /** Compatibility. */
  @inline final def apply(ma: MAB): M[A, B] = leibniz(ma)
}

sealed abstract class Unapply2_0 {
  /**Unpack a value of type `M0[F[_], A0, B0]` into types `[a, b]=M0[F, a, b]`, `A0`, and 'B9', given an instance of `TC` */
  implicit def unapplyMFAB[TC[_[_, _]], F[_], M0[F[_], _, _], A0, B0](implicit TC0: TC[M0[F, ?, ?]]): Unapply2[TC, M0[F, A0, B0]] {
    type M[X, Y] = M0[F, X, Y]
    type A = A0
    type B = B0
  } =
    new Unapply2[TC, M0[F, A0, B0]] {
      type M[X, Y] = M0[F, X, Y]
      type A = A0
      type B = B0
      def TC = TC0
      def leibniz = refl
    }
}

object Unapply2 extends Unapply2_0 {
  /** Fetch a well-typed `Unapply2` for the given typeclass and type. */
  def apply[TC[_[_, _]], MAB](implicit U: Unapply2[TC, MAB]): U.type {
    type M[X, Y] = U.M[X, Y]
    type A = U.A
    type B = U.B
  } = U

  /**Unpack a value of type `M0[A0, B0]` into types `M0`, `A`, and 'B', given an instance of `TC` */
  implicit def unapplyMAB[TC[_[_, _]], M0[_, _], A0, B0](implicit TC0: TC[M0]): Unapply2[TC, M0[A0, B0]] {
    type M[X, Y] = M0[X, Y]
    type A = A0
    type B = B0
  } =
    new Unapply2[TC, M0[A0, B0]] {
      type M[X, Y] = M0[X, Y]
      type A = A0
      type B = B0
      def TC = TC0
      def leibniz = refl
    }
}

trait Unapply21[TC[_[_, _], _], MAB]{
  type M[_, _]
  type A
  type B
  def TC: TC[M, A]

  def leibniz: MAB === M[A, B]
  @inline final def apply(mabc: MAB): M[A, B] = leibniz(mabc)
}

object Unapply21 {
  /** Fetch a well-typed `Unapply21` for the given typeclass and type. */
  def apply[TC[_[_, _], _], MAB](implicit U: Unapply21[TC, MAB]): U.type {
    type M[X, Y] = U.M[X, Y]
    type A = U.A
    type B = U.B
  } = U

  implicit def unapply210MFABC[TC[_[_, _], _], F[_,_], M0[_[_], _, _], A0, B0, C](implicit TC0: TC[λ[(α, β) => M0[F[α, ?], C, β]], A0]): Unapply21[TC, M0[F[A0, ?], C, B0]]{
    type M[X, Y] = M0[F[X, ?], C, Y]
    type A = A0
    type B = B0
  } =
    new Unapply21[TC, M0[F[A0, ?], C, B0]]{
      type M[X, Y] = M0[F[X, ?], C, Y]
      type A = A0
      type B = B0

      def TC = TC0
      def leibniz = refl
    }
}

trait UnapplyProduct[TC[_[_]], MA, MB] {
  type M[X]
  type A
  type B
  def TC: TC[M]
  type MA_ = MA
  def _1(ma: MA): M[A]
  def _2(mb: MB): M[B]
}

object UnapplyProduct {
  import Isomorphism.<~>

  /** Fetch a well-typed `UnapplyProduct` for the given typeclass and types. */
  def apply[TC[_[_]], MA, MB](implicit U: UnapplyProduct[TC, MA, MB]): U.type {
    type M[A] = U.M[A]
    type A = U.A
    type B = U.B
  } = U

  /**
   * This is a workaround that allows us to approximate multiple implicit
   * parameter sections (which Scala does not currently support). See this gist
   * by Miles Sabin for the original context:
   *
   *   https://gist.github.com/milessabin/cadd73b7756fe4097ca0
   *
   * The key idea is that we can use an intermediate type to capture the type
   * members of the two `Unapply` instances in such a way that we can refer to
   * them in the implicit parameter list.
   */
  case class SingletonOf[T, U <: { type A; type M[_] }](widen: T { type A = U#A; type M[x] = U#M[x] })

  object SingletonOf {
    implicit def mkSingletonOf[T <: { type A; type M[_] }](implicit t: T): SingletonOf[T, t.type] =
      SingletonOf(t)
  }

  implicit def unapply[TC[_[_]], MA0, MB0, U1 <: { type A; type M[_] }, U2 <: { type A; type M[_] }](implicit
    sU1: SingletonOf[Unapply[TC, MA0], U1],
    sU2: SingletonOf[Unapply[TC, MB0], U2],
    iso: U1#M <~> U2#M
  ): UnapplyProduct[TC, MA0, MB0] {
    type M[x] = U1#M[x]
    type A = U1#A
    type B = U2#A
  } = new UnapplyProduct[TC, MA0, MB0] {
    type M[x] = U1#M[x]
    type A = U1#A
    type B = U2#A
    def TC = sU1.widen.TC
    def _1(ma: MA0) = sU1.widen(ma)
    def _2(mb: MB0) = iso.from(sU2.widen(mb))
  }
}

Other Scala examples (source code examples)

Here is a short list of links related to this Scala Unapply.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.