How to reduce constrained HList - scala

How to fix the code below so it works?
object Foo {
object sum extends Poly {
implicit def caseFoo = use((f1: Int, f2: Int) => f1 + f2)
}
def foo[L <: HList : <<:[Int]#λ](l: L): Int = {
l.reduceLeft(sum)
// Error: could not find implicit value for parameter reducer: shapeless.ops.hlist.LeftReducer[L,com.struct.Foo.sum.type]
// l.reduceLeft(sum)
// Error: not enough arguments for method reduceLeft: (implicit reducer: shapeless.ops.hlist.LeftReducer[L,com.struct.Foo.sum.type])reducer.Out.
// Unspecified value parameter reducer.
}
}
Additionally. How to change it so it reduces HList of any Numerics?
Update:
Please consider fuller example of my problem:
import shapeless._
trait Bar {
def foo: Int
}
case class Foo[L <: HList](l: L) extends Bar {
object sum extends Poly {
implicit def caseFoo[A: Numeric] = use((f1: A, f2: A) => f1 + f2)
//Error: type mismatch;
//found : A
//required: String
}
override def foo(implicit reducer: LeftReducer[L, sum.type]): Int = reducer(l)
//Error: type mismatch;
//found : reducer.Out
//required: Int
}
Update:
package com.test
import shapeless.ops.hlist.LeftReducer
import shapeless.{HList, HNil, Poly}
trait Bar {
def foo: Int
}
case class Foo[L <: HList](list: L) extends Bar {
import Numeric.Implicits._
object sum extends Poly {
implicit def caseFoo[A: Numeric] = use((f1: A, f2: A) => f1 + f2)
}
class MkFoo[T] {
def apply(l: L)(implicit reducer: LeftReducer.Aux[L, sum.type, T]): T = reducer(l)
}
override def foo: Int = (new MkFoo[Int]())(list)
// Error: could not find implicit value for parameter reducer: shapeless.ops.hlist.LeftReducer.Aux[L,Foo.this.sum.type,Int]
}
object Testing {
def main(args: Array[String]): Unit = {
val b:Bar = Foo(1 :: 2 :: 3 :: HNil)
println(b.foo)
}
}

The LUBConstraint.<<: type is unconstructive in sense that it could only be evident that all HList members have some type, but can not derive anything from it.
To use reduceLeft method you need specifically LeftReducer operation provider. You can require it in your method directly.
import shapeless._, ops.hlist._
object Foo {
import Numeric.Implicits._
object sum extends Poly {
implicit def caseFoo[A: Numeric] = use((f1: A, f2: A) => f1 + f2)
}
def foo[L <: HList](l: L)(implicit reducer: LeftReducer[L, sum.type]): reducer.Out =
reducer(l)
}
Foo.foo(1 :: 2 :: 3 :: HNil) // res0: Int = 6
Foo.foo(1.0 :: 2.0 :: 3.0 :: HNil) // res1: Double = 6.0
Update
If you need direct evidence, that your result will be of some result type you can use additional type argument, but that needs separation of type parameters via the Typed Maker pattern
object Foo {
import Numeric.Implicits._
object sum extends Poly {
implicit def caseFoo[A: Numeric] = use((f1: A, f2: A) => f1 + f2)
}
def foo[T] = new MkFoo[T]
class MkFoo[T] {
def apply[L <: HList](l: L)(implicit reducer: LeftReducer.Aux[L, sum.type, T]): T = reducer(l)
}
}
now
Foo.foo[Int](1 :: 2 :: 3 :: HNil)
Foo.foo[Double](1.0 :: 2.0 :: 3.0 :: HNil)
will still produce correct result, while
Foo.foo[Double](1 :: 2 :: 3 :: HNil)
will fail at compile time

This works:
package com.test
import shapeless.{::, Generic, HList, HNil, Lazy}
trait Bar {
def foo: Int
}
case class Foo[L <: HList](list: L)(implicit ev: SizeCalculator[L]) extends Bar {
override def foo: Int = ev.size(list)
}
object Testing {
def main(args: Array[String]): Unit = {
val b: Bar = Foo(1 :: 2 :: 3 :: HNil)
println(b.foo)
}
}
sealed trait SizeCalculator[T] {
def size(value: T): Int
}
object SizeCalculator {
// "Summoner" method
def apply[A](implicit enc: SizeCalculator[A]): SizeCalculator[A] = enc
// "Constructor" method
def instance[A](func: A => Int): SizeCalculator[A] = new SizeCalculator[A] {
def size(value: A): Int = func(value)
}
import Numeric.Implicits._
implicit def numericEncoder[A: Numeric]: SizeCalculator[A] = new SizeCalculator[A] {
override def size(value: A): Int = value.toInt()
}
implicit def hnilEncoder: SizeCalculator[HNil] = instance(hnil => 0)
implicit def hlistEncoder[H, T <: HList](
implicit
hInstance: Lazy[SizeCalculator[H]],
tInstance: SizeCalculator[T]
): SizeCalculator[H :: T] = instance {
case h :: t =>
hInstance.value.size(h) + tInstance.size(t)
}
implicit def genericInstance[A, R](
implicit
generic: Generic.Aux[A, R],
rInstance: Lazy[SizeCalculator[R]]
): SizeCalculator[A] = instance { value => rInstance.value.size(generic.to(value)) }
def computeSize[A](value: A)(implicit enc: SizeCalculator[A]): Int = enc.size(value)
}

Related

How to extract types from a tuple that implements a typeclass

Function a can receive single argument or a tuple, these arguments need to be members of typeclass StringIdentifiable
How to extract and decompose tuple type into types that also have instances of the typeclass
#typeclass trait StringIdentifiable[M] {
def identify(id: M): String
}
def a[K: StringIdentifiable] (k:K){
k match{
case (k1) =>
implicitly[StringIdentifiable[K]].identify(k1)
case (k1,k2) =>
implicitly[StringIdentifiable[k1.type]].identify(k1)
implicitly[StringIdentifiable[k2.type]].identify(k2)
}
I get error in the second match:
Could not find an instance of StringIdentifiable for k1.type
k1.type, k2.type are singleton types. Try
#typeclass trait StringIdentifiable[M] {
def identify(id: M): String
}
object StringIdentifiable {
implicit def one[K]: StringIdentifiable[K] = ???
implicit def two[K1: StringIdentifiable, K2: StringIdentifiable]: StringIdentifiable[(K1, K2)] = {
new StringIdentifiable[(K1, K2)] {
override def identify(id: (K1, K2)): String = id match {
case (k1,k2) =>
implicitly[StringIdentifiable[K1]].identify(k1)
implicitly[StringIdentifiable[K2]].identify(k2)
???
}
}
}
}
def a[K: StringIdentifiable](k:K): String = implicitly[StringIdentifiable[K]].identify(k)
You can do this with shapeless. For instance:
import shapeless._, ops.hlist._
object MyPoly extends Poly2 {
implicit def foo[A] = at[A, StringIdentifiable[A]]( (a, f) => f.identify(a) )
}
def a[K: StringIdentifiable, L <: HList, O <: HList](k: K)(
implicit
gen: Generic.Aux[K, L], // decompose K into HList L
lift: LiftAll.Aux[StringIdentifiable, L, O], // find an instance of StringIdentifiable for every element of L
zip: ZipWith[L, O, MyPoly.type] // zip L with its typeclass instances and map the results with the polymorphic function MyPoly
): String :: zip.Out = {
val l = gen.to(k)
val o = lift.instances
implicitly[StringIdentifiable[K]].identify(k) :: zip(l, o)
}
implicit def id1[A,B]: StringIdentifiable[(A, B)] = _ => "1"
implicit val id2: StringIdentifiable[String] = _ => "2"
implicit val id3: StringIdentifiable[Int] = _ => "3"
a(("foo", 42)) // 1 :: 2 :: 3 :: HNil
A full solution to your problem (IIUC) probably consists of using shapeless to automatically generate StringIdentifiable instances for all tuples.
trait StringIdentifiable[M] {
def identify(id: M): String
}
object StringIdentifiable {
object MyPoly extends Poly2 {
implicit def foo[A] = at[A, StringIdentifiable[A]]( (a, f) => f.identify(a) )
}
implicit def mkSI[K, L <: HList, O <: HList](
implicit
tup: IsTuple[K],
gen: Generic.Aux[K, L],
lift: LiftAll.Aux[StringIdentifiable, L, O],
zip: ZipWith[L, O, MyPoly.type]
): StringIdentifiable[K] = {
val o = lift.instances
k => {
val l = gen.to(k)
zip(l, o).mkString("(", ", ", ")")
}
}
}

Shapeless and annotations

I would like to have some function applied to fields in a case class, that are annotated with MyAnnotation. The idea is to transform type T into its generic representation, extract annotations, zip, fold right (or left) to reconstruct a generic representation and finally get back to type T. I followed the answer provided here and this gist.
I'm using scala 2.11.12 and shapeless 2.3.3.
Hereafter is my code:
import shapeless._
import shapeless.ops.hlist._
case class MyAnnotation(func: String) extends scala.annotation.StaticAnnotation
trait Modifier[T] {
def modify(t: T): T
}
object Modifier {
def apply[A: Modifier]: Modifier[A] = implicitly[Modifier[A]]
def create[T](func: T => T): Modifier[T] = new Modifier[T] { override def modify(t: T): T = func(t) }
private def id[T](t: T) = t
implicit val stringModifier: Modifier[String] = create(id)
implicit val booleanModifier: Modifier[Boolean] = create(id)
implicit val byteModifier: Modifier[Byte] = create(id)
implicit val charModifier: Modifier[Char] = create(id)
implicit val doubleModifier: Modifier[Double] = create(id)
implicit val floatModifier: Modifier[Float] = create(id)
implicit val intModifier: Modifier[Int] = create(id)
implicit val longModifier: Modifier[Long] = create(id)
implicit val shortModifier: Modifier[Short] = create(id)
implicit val hnilModifier: Modifier[HNil] = create(id)
implicit def hlistModifier[H, T <: HList, AL <: HList](
implicit
hser: Lazy[Modifier[H]],
tser: Modifier[T]
): Modifier[H :: T] = new Modifier[H :: T] {
override def modify(ht: H :: T): H :: T = {
ht match {
case h :: t =>
hser.value.modify(h) :: tser.modify(t)
}
}
}
implicit val cnilModifier: Modifier[CNil] = create(id)
implicit def coproductModifier[L, R <: Coproduct](
implicit
lser: Lazy[Modifier[L]],
rser: Modifier[R]
): Modifier[L :+: R] = new Modifier[L :+: R] {
override def modify(t: L :+: R): L :+: R = t match {
case Inl(l) => Inl(lser.value.modify(l))
case Inr(r) => Inr(rser.modify(r))
}
}
object Collector extends Poly2 {
implicit def myCase[ACC <: HList, E] = at[(E, Option[MyAnnotation]), ACC] {
case ((e, None), acc) => e :: acc
case ((e, Some(MyAnnotation(func))), acc) => {
println(func)
e :: acc
}
}
}
implicit def genericModifier[T, HL <: HList, AL <: HList, ZL <: HList](
implicit
gen: Generic.Aux[T, HL],
ser: Lazy[Modifier[HL]],
annots: Annotations.Aux[MyAnnotation, T, AL],
zip: Zip.Aux[HL :: AL :: HNil, ZL],
rightFolder: RightFolder[ZL, HNil.type, Collector.type]
): Modifier[T] = new Modifier[T] {
override def modify(t: T): T = {
val generic = gen.to(t)
println(generic)
val annotations = annots()
println(annotations)
val zipped = zip(generic :: annotations :: HNil)
println(zipped)
val modified = zipped.foldRight(HNil)(Collector)
println(modified)
val typed = gen.from(generic) // temporary
typed
}
}
}
The code above compiles. However, when instanciating a Modifier in a test:
case class Test(a: String, #MyAnnotation("sha1") b: String)
val test = Test("A", "B")
val modifier: Modifier[Test] = implicitly
the test file does not compile and give the following error:
[error] ambiguous implicit values:
[error] both value StringCanBuildFrom in object Predef of type =>
scala.collection.generic.CanBuildFrom[String,Char,String]
[error] and method $conforms in object Predef of type [A]=> <:<[A,A]
[error] match expected type T
[error] val ser1: Modifier[Test] = implicitly
The problem seems to come from the right folder definition: when removing rightFolder from the list of implicits in genericModifier, then it works:
implicit def genericModifier[T, HL <: HList, AL <: HList, ZL <: HList](
implicit
gen: Generic.Aux[T, HL],
ser: Lazy[Modifier[HL]],
annots: Annotations.Aux[MyAnnotation, T, AL],
zip: Zip.Aux[HL :: AL :: HNil, ZL]/*,
rightFolder: RightFolder[ZL, HNil.type, Collector.type]*/
): Modifier[T] = new Modifier[T] {
override def modify(t: T): T = {
val generic = gen.to(t)
println(generic)
val annotations = annots()
println(annotations)
val zipped = zip(generic :: annotations :: HNil)
println(zipped)
/*val modified = zipped.foldRight(HNil)(Collector)
println(modified)*/
val typed = gen.from(generic) // temporary
typed
}
}
What is wrong?
There are several mistakes in your code:
defining Poly just for Option is too rough (pattern matching is performed at runtime and compiler should know definitions for Some and None at compile time)
HNil should be instead of HNil.type and HNil : HNil instead of HNil (types HNil and HNil.type are different)
compiler doesn't know that RightFolder actually returns the original HList type, so you should use RightFolder.Aux type.
Correct code is
import shapeless.ops.hlist.{RightFolder, Zip}
import shapeless.{::, Annotations, Generic, HList, HNil, Lazy, Poly2}
import scala.annotation.StaticAnnotation
object App {
case class MyAnnotation(func: String) extends StaticAnnotation
object Collector extends Poly2 {
// implicit def myCase[ACC <: HList, E] = at[(E, Option[PII]), ACC] {
// case ((e, None), acc) => e :: acc
// case ((e, Some(MyAnnotation(func))), acc) => {
// println(func)
// e :: acc
// }
// }
implicit def someCase[ACC <: HList, E]: Case.Aux[(E, Some[MyAnnotation]), ACC, E :: ACC] = at {
case ((e, Some(MyAnnotation(func))), acc) =>
println(func)
e :: acc
}
implicit def noneCase[ACC <: HList, E]: Case.Aux[(E, None.type), ACC, E :: ACC] = at {
case ((e, None), acc) => e :: acc
}
}
trait Modifier[T] {
def modify(t: T): T
}
implicit def hListModifier[HL <: HList]: Modifier[HL] = identity(_)
// added as an example, you should replace this with your Modifier for HList
implicit def genericModifier[T, HL <: HList, AL <: HList, ZL <: HList](implicit
gen: Generic.Aux[T, HL],
ser: Lazy[Modifier[HL]],
annots: Annotations.Aux[MyAnnotation, T, AL],
zip: Zip.Aux[HL :: AL :: HNil, ZL],
rightFolder: RightFolder.Aux[ZL, HNil/*.type*/, Collector.type, HL /*added*/]
): Modifier[T] = new Modifier[T] {
override def modify(t: T): T = {
val generic = gen.to(t)
println(generic)
val annotations = annots()
println(annotations)
val zipped = zip(generic :: annotations :: HNil)
println(zipped)
val modified = zipped.foldRight(HNil : HNil /*added*/)(Collector)
println(modified)
val typed = gen.from(modified)
typed
}
}
case class Test(a: String, #MyAnnotation("sha1") b: String)
val test = Test("A", "B")
val modifier: Modifier[Test] = implicitly[Modifier[Test]]
def main(args: Array[String]): Unit = {
val test1 = modifier.modify(test) // prints "sha1"
println(test1) // Test(A,B)
}
}

Shapeless HList with ClassTags

I have a quite simple function that is able to instantiate the class of type C:
def parse[C: ClassTag]: C = implicitly[ClassTag[C]].runtimeClass.getCanonicalName match {
case "int" ⇒ 10.asInstanceOf[C]
case "double" ⇒ 10d.asInstanceOf[C]
case "java.lang.String" ⇒ "qwerty".asInstanceOf[C]
}
parse[Int] // res0: Int = 10
parse[Double] // res1: Double = 10.0
parse[String] // res2: qwerty = String
I'd like to introduce second function:
def parseAll[T <: HList]: T = ???
And use it as follows:
val defaults: Int :: Double :: String :: HNil = parseAll[Int :: Double :: String :: HNil]
// res3: shapeless.::[Int,shapeless.::[Double,shapeless.::[String,shapeless.HNil]]] = 10 :: 10.0 :: qwerty :: HNil
Any ideas how can I implement such function?
You can define type class ParseAll:
import shapeless.{::, HList, HNil}
import scala.reflect.ClassTag
def parse[C: ClassTag]: C = implicitly[ClassTag[C]].runtimeClass.getCanonicalName match {
case "int" ⇒ 10.asInstanceOf[C]
case "double" ⇒ 10d.asInstanceOf[C]
case "java.lang.String" ⇒ "qwerty".asInstanceOf[C]
}
def parseAll[T <: HList](implicit p: ParseAll[T]): T = p.apply
trait ParseAll[T <: HList] {
def apply: T
}
object ParseAll {
implicit def hCons[H: ClassTag, T <: HList](implicit p: ParseAll[T]): ParseAll[H :: T] = new ParseAll[H :: T] {
override def apply: H :: T = parse[H] :: p.apply
}
implicit val hNil: ParseAll[HNil] = new ParseAll[HNil] {
override def apply: HNil = HNil
}
}
parseAll[Int :: Double :: String :: HNil] // 10 :: 10.0 :: "qwerty" :: HNil
Actually you can do this without reflection:
import shapeless.{::, HList, HNil}
def parse[C](implicit p: Parse[C]): C = p.apply
trait Parse[C] {
def apply: C
}
object Parse {
implicit val int: Parse[Int] = new Parse[Int] {
override def apply: Int = 10
}
implicit val double: Parse[Double] = new Parse[Double] {
override def apply: Double = 10.0
}
implicit val string: Parse[String] = new Parse[String] {
override def apply: String = "qwerty"
}
}
def parseAll[T <: HList](implicit p: ParseAll[T]): T = p.apply
trait ParseAll[T <: HList] {
def apply: T
}
object ParseAll {
implicit def hCons[H, T <: HList](implicit parse: Parse[H], parseAll: ParseAll[T]): ParseAll[H :: T] = new ParseAll[H :: T] {
override def apply: H :: T = parse.apply :: parseAll.apply
}
implicit def hNil: ParseAll[HNil] = new ParseAll[HNil] {
override val apply: HNil = HNil
}
}
parseAll[Int :: Double :: String :: HNil] // 10 :: 10.0 :: "qwerty" :: HNil

Type safe type combinations with shapeless

Having the following code:
import shapeless.{::, Generic, HList, HNil, Lazy}
object Problem {
trait In {
def bar: Double
}
trait A {
def foo: Int
type I <: In
}
/////////////////////////////////////////////////////
final case class A1In(d: Double) extends In {
override def bar: Double = 1.1 + d
}
final case class A1() extends A {
override def foo: Int = 1
override type I = A1In
}
final case class A2In(d: Double) extends In {
override def bar: Double = 1.1 + d
}
final case class A2() extends A {
override def foo: Int = 1
override type I = A2In
}
final case class AListIn[T <: HList](items: T)(implicit ev: isIn[T]) extends In {
override def bar = 1.1
}
final case class AList[T <: HList](items: T)(implicit ev: isA[T]) extends A {
override def foo: Int = 555
override type I = AListIn[???]
}
trait isA[T] {
def aux_foo(value: T): Int
}
trait isIn[T] {
def aux_bar(value: T): Double
}
/////////////////////////////////////////////////////
def alloc(a: A): In = ????
def usage() = {
val a1: A1 = A1()
val a2: A2 = A2()
val l: AList[::[A1, ::[A2, ::[A1, HNil]]]] = AList(a1 :: a2 :: a1 :: HNil)
val a1In: A1In = A1In(1.2)
val a2In: A2In = A2In(9.3)
val lIn: AListIn[::[A2In, ::[A1In, HNil]]] = AListIn(a2In :: a1In :: HNil)
}
}
How can I fix it so it works as expected?
E.g how do I get correct type in place of ??? which is a proper type HList being result of applying isA -> isIn type mapping. The mapping must follow the natural association of A -> In mapping defined as type I <: In in trait A
And how to implement alloc function which for any concrete instance of In will produce corresponding instance of A?
Should concrete implementations of In be path dependent types of corresponding As?
Below is the code for isA the code for isIn is analogous
trait isA[T] {
def aux_foo(value: T): Int
}
object isA {
// "Summoner" method
def apply[T](implicit enc: isA[T]): isA[T] = enc
// "Constructor" method
def instance[T](func: T => Int): isA[T] = new isA[T] {
override def aux_foo(value: T): Int = func(value)
}
implicit def a1Encoder: isA[A1] = instance(i => 4)
implicit def a2Encoder: isA[A2] = instance(i => 9)
implicit def hnilEncoder: isA[HNil] = instance(hnil => 0)
implicit def hlistEncoder[H, T <: HList](implicit
hInstance: Lazy[isA[H]],
tInstance: isA[T]
): isA[H :: T] = instance {
case h :: t => hInstance.value.aux_foo(h) + tInstance.aux_foo(t)
}
implicit def genericInstance[A, R](implicit
generic: Generic.Aux[A, R],
rInstance: Lazy[isA[R]]
): isA[A] = instance { value => rInstance.value.aux_foo(generic.to(value)) }
}

Parse List[String] into HList

I would like to write def parse[T <: HList](list: List[String]): Validation[T]. list could be List("fooid", "barid"), and T FooId :: BarId :: HNil, and a typeclass Parse[T] which implements String => Validation[FooId]. How would I write said parse, which parses the list into T? I'm not sure how to summon the implicit typeclasses for each of the elements of T.
We can adapt the code from shapeless.ops.traversable.FromTraversable.
I'm not sure what your Validation type is, but I used it as an alias for scalaz.ValidationNel[String, A] below (mostly so I could use the string syntax to easily give me some Parse instances).
import scalaz.{Validation => _, _}, Scalaz._
type Validation[A] = ValidationNel[String, A]
trait Parse[T] {
def apply(s: String): Validation[T]
}
object Parse {
def fromScalazParse[E <: Exception, T](f: String => scalaz.Validation[E, T]) =
new Parse[T] {
def apply(s: String): Validation[T] =
f(s).leftMap(_.getMessage).toValidationNel
}
implicit val booleanParse = fromScalazParse(_.parseBoolean)
implicit val intParse = fromScalazParse(_.parseInt)
implicit val doubleParse = fromScalazParse(_.parseDouble)
}
With the Parser type class sorted, we can now create a type class based on FromTraversable to parse a List[String] and give us a Validation[A :: B :: HNil] :
import shapeless._
import scala.collection.GenTraversable
trait FromTraversableParsed[Out <: HList] extends Serializable {
def apply(l: GenTraversable[String]) : Validation[Out]
}
object FromTraversableParsed {
def apply[Out <: HList](implicit from: FromTraversableParsed[Out]) = from
implicit val hnilFromTraversableParsed =
new FromTraversableParsed[HNil] {
def apply(l: GenTraversable[String]): Validation[HNil] =
if(l.isEmpty) HNil.successNel[String]
else "Traversable is not empty".failureNel[HNil]
}
implicit def hlistFromTraversableParsed[OutH, OutT <: HList](implicit
ftpT: FromTraversableParsed[OutT],
parseH: Parse[OutH]
): FromTraversableParsed[OutH :: OutT] =
new FromTraversableParsed[OutH :: OutT] {
def apply(l : GenTraversable[String]) : Validation[OutH :: OutT] =
if(l.isEmpty) "Empty traversable".failureNel[OutH :: OutT]
else (parseH(l.head) |#| ftpT(l.tail))(_ :: _)
}
}
We can add some syntax to make using FromTraversableParsed a little bit easier :
implicit class ParseStringListOps(val strings: List[String]) extends AnyVal {
def parse[L <: HList](implicit ftp: FromTraversableParsed[L]): Validation[L] =
ftp(strings)
}
Now we can do :
List("1", "true", "3.0").parse[Int :: Boolean :: Double :: HNil]
// Validation[Int :: Boolean :: Double :: HNil] = Success(1 :: true :: 3.0 :: HNil)