MapRes and Exotic data

So far only HKD and tuples have been used in queries and results, but there are far more types you can use here. In theory, any type that has instances of ApplyKC and TraverseKC can be used in queries.

However, Scala's type inference does not work well enough if the destination type does not have the kind F[_[_]]. This excludes types, or other non-simple types. To solve this problem, DataPrism introduces the type MapRes[F, R] { type K[A[_]] }. MapRes serves as an evidence that the type R incorporates the type F on its elements, and that the type K[F] = R. For example MapRes[DbValue, (DbValue[Boolean], DbValue[Int])] says that in the type (DbValue[Boolean], DbValue[Int]), the values are wrapped in DbValue. It also indicates that the type K[F[_]] = (F[Boolean], F[Int]).

MapRes also contains functions to convert to and from K[F], in addition to ApplyKC and TraverseKC instances.

Here is a list of all the types MapRes will handle. The Aux type of MapRes will be used to show all the types of MapRes. Where a type could be anything, a type lambda will be used to show that the types could be something else.

[F[_[_]], G[_]] =>> MapRes.Aux[F[G], G, F]

MapRes handles higher kinded data, or other types with the kind F[_[_]].

[F[_], T <: NonEmptyTuple] =>> MapRes.Aux[F, T, [F0[_]] =>> Tuple.Map[Tuple.InverseMap[T, F], F0]

MapRes handles non-empty tuples, as long as all the elements are mapped by the required type, for example DbValue.

[F[_], A] =>> MapRes.Aux[F, F[A], [F0[_]] =>> F0[A]

MapRes handles single values of type F[A].

Tuple recursion

If all the elements of a tuple have instances of MapRes, so does the tuple itself

Lifting Apply and Traverse to MapRes

If the MapRes instance [F[_], V, MRK[_[_]]] =>> MapRes.Aux[F, V, MRK] exists, and G[_] is a type with instances Apply[G] and Traverse[G], then there is also a MapRes of type [F[_], G[_], V, MRK[_[_]]] =>> MapRes.Aux[F, G[V], [F0[_]] =>> G[MRK[F0]]

What this practically mean is that Option[DbValue[Int]] could for example be a valid type, and will follow the semantics of the Apply and Traverse instances for G.

Think of this as a sort of metaprogramming for the generated SQL.

Derived instances of ApplyKC and TraverseKC also supports the same principle.

Beware Lists

Beware of using List in the above manner. List will operate in accordance to it's Apply instance. For example, map2 on two lists of 3 elements each will produce an element of 9 elements, combining the cross product of the two lists. If you want zipping behavior, use ZipList instead.