Skip to content

Instantly share code, notes, and snippets.

@Katrix
Created October 4, 2019 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Katrix/b3da2b1c66b11eea69484c63c2c9d262 to your computer and use it in GitHub Desktop.
Save Katrix/b3da2b1c66b11eea69484c63c2c9d262 to your computer and use it in GitHub Desktop.
object AddRemoveSeperate {
type Outer[W[_], E[_], A] = W[E[A]]
type Inner[W[_], E[_], A] = E[W[A]]
type SingleWrapper[W[_], E[_], A] = W[A]
type SingleExisting[W[_], E[_], A] = E[A]
trait Add[W[_], To[_[_], _[_], _], In] {
type Out
}
object Add {
type Aux[W[_], To[_[_], _[_], _], In, Out0] = Add[W, To, In] {
type Out = Out0
}
def apply[W[_], To[_[_], _[_], _], In](
implicit add: Add[W, To, In]
): Aux[W, To, In, add.Out] = add
implicit def valueTypes[W[_], To[_[_], _[_], _], E[_], A]: Add.Aux[W, To, E[A], To[W, E, A]] =
new Add[W, To, E[A]] {
type Out = To[W, E, A]
}
}
trait RemoveOuter[W[_], In] {
type Out
}
object RemoveOuter {
type Aux[W[_], In, Out0] = RemoveOuter[W, In] {
type Out = Out0
}
def apply[W[_], In](
implicit removeOuter: RemoveOuter[W, In]
): Aux[W, In, removeOuter.Out] = removeOuter
implicit def valueTypes[W[_], E[_], A]: RemoveOuter.Aux[W, W[E[A]], E[A]] =
new RemoveOuter[W, W[E[A]]] {
type Out = E[A]
}
}
trait RemoveInner[W[_], In] {
type Out
}
object RemoveInner {
type Aux[W[_], In, Out0] = RemoveInner[W, In] {
type Out = Out0
}
def apply[W[_], In](
implicit removeInner: RemoveInner[W, In]
): Aux[W, In, removeInner.Out] = removeInner
implicit def valueTypes[W[_], E[_], A]: RemoveInner.Aux[W, E[W[A]], E[A]] =
new RemoveInner[W, E[W[A]]] {
type Out = E[A]
}
}
val res1 = Add[Option, Outer, Seq[Int]]
implicitly[res1.Out =:= Option[Seq[Int]]]
val res2 = Add[Option, Inner, Seq[Int]]
implicitly[res2.Out =:= Seq[Option[Int]]]
val res3 = RemoveOuter[Option, Option[Seq[Int]]]
implicitly[res3.Out =:= Seq[Int]]
val res4 = RemoveInner[Option, Seq[Option[Int]]]
implicitly[res4.Out =:= Seq[Int]]
}
object AddRemoveOne {
type Outer[W[_], E[_], A] = W[E[A]]
type Inner[W[_], E[_], A] = E[W[A]]
type SingleWrapper[W[_], E[_], A] = W[A]
type SingleExisting[W[_], E[_], A] = E[A]
trait AddRemove[W[_], From[_[_], _[_], _], To[_[_], _[_], _], In] {
type Out
}
object AddRemove {
type Aux[W[_], From[_[_], _[_], _], To[_[_], _[_], _], In, Out0] = AddRemove[W, From, To, In] {
type Out = Out0
}
def apply[W[_], From[_[_], _[_], _], To[_[_], _[_], _], In](
implicit findReplace: AddRemove[W, From, To, In]
): Aux[W, From, To, In, findReplace.Out] = findReplace
implicit def valueTypes[W[_], From[_[_], _[_], _], To[_[_], _[_], _], E[_], A]
: AddRemove.Aux[W, From, To, From[W, E, A], To[W, E, A]] =
new AddRemove[W, From, To, From[W, E, A]] {
type Out = To[W, E, A]
}
}
/*
None of these work
val res1 = AddRemove[Option, SingleExisting, Outer, Seq[Int]]
implicitly[res1.Out =:= Option[Seq[Int]]]
val res2 = AddRemove[Option, SingleExisting, Inner, Seq[Int]]
implicitly[res2.Out =:= Seq[Option[Int]]]
val res3 = AddRemove[Option, Outer, SingleExisting, Option[Seq[Int]]]
implicitly[res3.Out =:= Seq[Int]]
val res4 = AddRemove[Option, Inner, SingleExisting, Seq[Option[Int]]]
implicitly[res4.Out =:= Seq[Int]]
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment