Skip to content

Instantly share code, notes, and snippets.

@sir-wabbit
Last active April 26, 2017 15:34
Show Gist options
  • Select an option

  • Save sir-wabbit/6d689e0e9d335863428257770a5bade5 to your computer and use it in GitHub Desktop.

Select an option

Save sir-wabbit/6d689e0e9d335863428257770a5bade5 to your computer and use it in GitHub Desktop.
trait Data { type Value }
final case class Value[N <: Data](value: N#Value) extends AnyVal
abstract class Nat protected () extends Data { type Value = Int }
final class Z extends Nat
final class S[N <: Nat] extends Nat
object Nat {
implicit val zValue: Value[Z] =
Value[Z](0)
implicit def sValue[N <: Nat](implicit N: Value[N]): Value[S[N]] =
Value[S[N]](N.value + 1)
}
sealed trait HKVec { type Size <: Nat }
object HKVec {
final class Nil extends HKVec { type Size = Z }
final class ::[Head[_], Tail <: HKVec] extends HKVec { type Size = S[Tail#Size] }
}
import HKVec._
sealed class Coproduct[L <: HKVec, A] { type Constructors = L; type Argument = A }
object Coproduct {
final case class View[L <: HKVec, A](tag: Int, value: Any) extends Coproduct[L, A]
}
final case class Index[L <: HKVec, H[_]](index: Int) extends AnyVal
trait Index1 {
implicit def case1[H[_], T <: HKVec, X[_]](implicit T: Index[T, X]): Index[H :: T, X] = Index(T.index)
}
object Index extends Index1 {
implicit def case0[T <: HKVec, X[_]](implicit S: Value[T#Size]): Index[X :: T, X] = Index(S.value)
}
final case class CoproductOps[L <: HKVec, H[_]](tag: Int) {
def inj[A](ha: H[A]): Coproduct[L, A] = Coproduct.View(tag, ha)
def proj[A](ca: Coproduct[L, A]): Option[H[A]] = ca match {
case Coproduct.View(t, a) if tag == t => Some(a.asInstanceOf[H[A]])
case _ => None
}
}
object CoproductOps {
implicit def case0[L <: HKVec, H[_]](implicit I: Index[L, H]): CoproductOps[L, H] = CoproductOps(I.index)
}
trait Foo[A, B]
trait Bar[A]
type FooBar[A, B] = Coproduct[({type L[C] = Foo[C, B]})#L :: Bar :: Nil, A]
def run[B]: Unit = {
implicitly[CoproductOps[Option :: List :: Nil, Option]]
implicitly[CoproductOps[Option :: List :: Nil, List]]
type L[a] = ({type l[a] = Either[Int, a]})#l[a]
implicitly[CoproductOps[L :: List :: Nil, List]]
implicitly[CoproductOps[L :: List :: Nil, L]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment