-
-
Save larsrh/61117429fab3c5ce4aa898ff56c0ba5c to your computer and use it in GitHub Desktop.
Attempt to get single compose method between optics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package vanilla | |
sealed trait Optic[G[_,_] <: Optic[G, _, _], S, A] { | |
def compose[F[_, _] <: Optic[F, _, _], B](o: F[A, B])(implicit lub : Lub[G,F]) : lub.T[S, B] = | |
lub.compose(self, o) | |
def self: G[S,A] | |
def desc: List[String] | |
} | |
case class Traversal[A,B](desc : List[String]) extends Optic[Traversal,A,B] { | |
def self = this | |
} | |
case class Lens[A,B](desc : List[String]) extends Optic[Lens,A,B] { | |
def self = this | |
} | |
trait Lub[F[_, _] <: Optic[F, _, _], G[_, _] <: Optic[G, _, _]]{ | |
// add witness that F[_,_] <: T[_,_] and G[_,_] <: T[_,_] | |
type T[_, _] <: Optic[T, _, _] | |
def compose[A, B, C](o1: F[A, B], o2: G[B, C]): T[A, C] | |
} | |
object Lub { | |
implicit val lensTraversal = new Lub[Lens, Traversal] { | |
override type T[A, B] = Traversal[A, B] | |
override def compose[A, B, C](o1: Lens[A, B], o2: Traversal[B, C]): Traversal[A, C] = Traversal(o1.desc ++ o2.desc) | |
} | |
implicit val traversalLens = new Lub[Traversal, Lens] { | |
override type T[A, B] = Traversal[A, B] | |
override def compose[A, B, C](o1: Traversal[A, B], o2: Lens[B, C]): Traversal[A, C] = Traversal(o1.desc ++ o2.desc) | |
} | |
implicit val lensLens = new Lub[Lens, Lens] { | |
override type T[A, B] = Lens[A, B] | |
override def compose[A, B, C](o1: Lens[A, B], o2: Lens[B, C]): Lens[A, C] = ??? | |
} | |
implicit val traversalTraversal = new Lub[Traversal, Traversal] { | |
override type T[A, B] = Traversal[A, B] | |
override def compose[A, B, C](o1: Traversal[A, B], o2: Traversal[B, C]): Traversal[A, C] = ??? | |
} | |
} | |
object Test extends App { | |
val foo: Lens[String, Int] = Lens(List("foo")) | |
val bar: Traversal[Int, String] = Traversal(List("bar")) | |
val foobar = foo compose bar | |
println(foobar.isInstanceOf[Traversal[String ,String]]) // true | |
val _foobar: Traversal[String, String] = foobar | |
val foobarfoo = foobar compose foo | |
println((foo compose bar compose foo).desc) // List(foo, bar, foo) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment