Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid going through the "tuple representation" #44

Open
vil1 opened this issue Jan 18, 2019 · 2 comments
Open

Avoid going through the "tuple representation" #44

vil1 opened this issue Jan 18, 2019 · 2 comments

Comments

@vil1
Copy link
Member

vil1 commented Jan 18, 2019

This should be done after #38.

We should search for to avoid going through the "tuple representation" of records in the functors we derive.

Currently, when processing a record like:

final case class Foo(i: Int, s: String, b: Boolean)

The functors we derive from schemas first convert instances of Foo to a value of type (Int, (String, Boolean)); there should be a way of expressing derivations that avoids this unnecessary step.

Solving this issue might require to change the type of the iso field in Union and Record, currently an Iso[A0, A].

@vil1
Copy link
Member Author

vil1 commented Jan 25, 2019

I have a bunch of vague ideas about this issue, I will try to see how far I can get.

@vil1
Copy link
Member Author

vil1 commented Jan 28, 2019

Writing down my main idea with the hope someone will be able to help me realising it.

It is about avoiding going through the tuple representation of records and only for interpreting into a covariant target (you have to start somewhere ^^).

lets take an example case class:

final case class Foo(i: Int, s: String, b: Boolean)

and a corresponding schema (isomorphisms eluded for brevity)

val foo = record( 
  "i" -*>: prim(ScalaInt) :*:
  "s" -*>: prim(ScalaString) :*:
  "b" -*>: prim(ScalaBool)
)

Which is a tree with this shape :

       Record
         |
        :*:
       /   \
    Int    :*:
          /   \
      String  Boolean

Since Foo is a case class, we have access to a curried function of type Int => String => Boolean => Foo:

val curriedCtr: Int => String => Boolean => Foo = (Foo.apply _).curried

Now, imagine we're able to carry some "context" along the traversal of our tree and that this context contains "some F[_]" where F is our target functor (and there is an Applicative[F] instance available).

When reaching the Record node while going down (the very first step of the recursion), we put F.point(curriedCtr) in our context (of type F[Int => String => Boolean => Foo].

After a few step we reach a first leaf (the Int node), and the algebra returns an F[Int] so we can combine it with the F[Int => String => Boolean => Foo] in our context (using ap) to obtain an F[String => Boolean => Foo] that we put back in our context.

We repeat the same mechanism when we reach the String leaf, using the produced F[String] to update the context to an F[Boolean => Foo].

Finally, when we reach the last leaf and repeat the same operation again, we end up with an F[Foo] in our context.

Traversing back up the two :*: nodes is a no-op, and getting back up to the Record node, we just return the F[Foo] we have in the context. The important point being that this F[Foo] never builds nor destructs any tuple to perform its work.

If you've read thus far, you probably agree that this sounds promising.

With an hyloM (to be implemented) using State to maintain the so-called context, we should be able to implement the traversal described above (I can detail that claim further if needed).

But the problem is that the type of the said context would have to change during the traversal (from F[Int => String => Boolean => Foo] to F[Foo] and everything in between).

Moreover, we must make sure that every time we reach a leaf Schema[A], the context is of type F[A => X] (for some type X), so a naive approach that would build this context around the existential type F[_] isn't an option.

So far, I have no idea how to achieve that...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant