Created
July 24, 2016 16:08
-
-
Save julien-truffaut/2de9c74de4e4ddbd268bbe6cd5a9bcee 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: Lub[Lens, Traversal] = 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: Lub[Traversal, Lens] = 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: Lub[Lens, Lens] = 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: Lub[Traversal, Traversal] = 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 | |
// all below fail | |
val _foobar: Traversal[String, String] = foobar | |
val foobarfoo = foobar compose foo | |
println((foo compose bar compose foo).desc) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment