Skip to content

Instantly share code, notes, and snippets.

@zainab-ali
Created March 31, 2017 21:03
Show Gist options
  • Save zainab-ali/ba2658d782cb326a697316310d131365 to your computer and use it in GitHub Desktop.
Save zainab-ali/ba2658d782cb326a697316310d131365 to your computer and use it in GitHub Desktop.
Zip record with tuples as values
package foo
import shapeless._
import shapeless.labelled.FieldType
import shapeless.ops.hlist._
/** This example zips two hlists together based on their keys and part of their values
*
*
* A left HList of type FieldType[Key, (A, LB)] :: LTail is zipped with a right HList which contains FieldType[Key, (A, RB)]
* to produce a FieldType[Key, (A, (LB, RB))]
*
* The implicit cannot be found
*/
trait Foo[L <: HList, R <: HList] {
type Out <: HList
}
object Foo {
type Aux[L <: HList, R <: HList, Out0 <: HList] = Foo[L, R] { type Out = Out0 }
implicit def base[R <: HList]: Aux[HNil, R, R] = ???
/** Given a left HList of type FieldType[Key, (A, LB)] :: LTail
* and a right HList which contains FieldType[Key, (A, RB)]
* produce a FieldType[Key, (A, (LB, RB))] :: OutTail
*/
implicit def recurse[Key, A, R <: HList, LB, RB, RTail <: HList, LTail <: HList, OutTail <: HList](
implicit ev0: shapeless.ops.record.Selector.Aux[R, Key, (A, RB)],
ev1: FilterNot.Aux[R, FieldType[Key, (A, RB)], RTail],
ev2: Aux[LTail, RTail, OutTail]
): Aux[FieldType[Key, (A, LB)] :: LTail, R, FieldType[Key, (A, (LB, RB))] :: OutTail] = ???
}
object TestFoo {
type Key
type ValueA
type ValueBL
type ValueBR
type HL = FieldType[Key, (ValueA, ValueBL)] :: HNil
type HR = FieldType[Key, (ValueA, ValueBR)] :: HNil
//it can be called explicitly
val f: Foo[HL, HR] = Foo.recurse[Key, ValueA, HR, ValueBL, ValueBR, HNil, HNil, HNil]
//all the required implicits can be found
the[shapeless.ops.record.Selector.Aux[HR, Key, (ValueA, ValueBR)]]
the[FilterNot.Aux[HR, FieldType[Key, (ValueA, ValueBR)], HNil]]
the[Foo.Aux[HNil, HNil, HNil]]
//but the implicit cannot be found
the[Foo[HL, HR]]
}
/** Strangely, it works without tuples
* This uses FieldType[Key, ValueL] instead of FieldType[Key, (ValueA, ValueL)]
*/
trait Bar[L <: HList, R <: HList] {
type Out <: HList
}
object Bar {
type Aux[L <: HList, R <: HList, Out0 <: HList] = Bar[L, R] { type Out = Out0 }
implicit def base[R <: HList]: Aux[HNil, R, R] = ???
implicit def recurse[Key, R <: HList, ValueL, ValueR, RTail <: HList, LTail <: HList, OutTail <: HList](
implicit ev0: shapeless.ops.record.Selector.Aux[R, Key, ValueR],
ev1: FilterNot.Aux[R, FieldType[Key, ValueR], RTail],
ev2: Aux[LTail, RTail, OutTail]
): Aux[FieldType[Key, ValueL] :: LTail, R, FieldType[Key, (ValueL, ValueR)] :: OutTail] = ???
}
object TestBar {
type Key
type ValueL
type ValueR
type HL = FieldType[Key, ValueL] :: HNil
type HR = FieldType[Key, ValueR] :: HNil
//no problem finding this
the[Bar[HL, HR]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment