2

Here is a simple example in shapeless 2.3.3:

  val book =
    ("author" ->> "Benjamin Pierce") ::
      ("title" ->> "Types and Programming Languages") ::
      ("id" ->> 262162091) ::
      ("price" ->> 44.11) ::
      HNil

  val v1 = book.values

  assert(v1.head == "Benjamin Pierce") // works fine

  // summoning Values[_] type class explicitly, the HList & TypeTag are optional
  case class HasValues[T <: HList: TypeTag](v: T) {

    def vs(implicit v: Values[T]): Values[T] = v
  }

  val _vs = HasValues(book).vs

  val v2 = book.values(_vs)

  assert(v2.head == "Benjamin Pierce") // compilation error!

The last line, despite v2 being syntactically identical to v1, gave the following error:

: could not find implicit value for parameter c: shapeless.ops.hlist.IsHCons[com.tribbloids.spike.shapeless_spike.RecordProblem._vs.Out]
one error found

Further investigation indicates that the type hierarchy of symbol v1 looks like this:

-+ String :: String :: Int :: Double :: shapeless.HNil
 :       `-+ [ 2 ARGS ] :
 :         !-+ String .................................................................................................................. [0]
 :         : !-+ CharSequence
 :         : : !-+ Object .................................................................................................................. [1]
 :         : :   !-- Any ..................................................................................................................... [2]
 :         : !-- Comparable[String]
 :         : :         `-+ [ 1 ARG ] :
 :         : :           !-- String .................................................................................................................. [0]
 :         : !-- java.io.Serializable .................................................................................................... [3]
 :         !-+ String :: Int :: Double :: shapeless.HNil
 :           :       `-+ [ 2 ARGS ] :
 :           :         !-- String .................................................................................................................. [0]
 :           :         !-+ Int :: Double :: shapeless.HNil
 :           :           :       `-+ [ 2 ARGS ] :
 :           :           :         !-+ Int
 :           :           :         : !-+ AnyVal .................................................................................................................. [4]
 :           :           :         :   !-- Any ..................................................................................................................... [2]
 :           :           :         !-+ Double :: shapeless.HNil
 :           :           :           :       `-+ [ 2 ARGS ] :
 :           :           :           :         !-+ Double
 :           :           :           :         : !-- AnyVal .................................................................................................................. [4]
 :           :           :           :         !-+ shapeless.HNil
 :           :           :           :           !-+ shapeless.HList ......................................................................................................... [5]
 :           :           :           :             !-+ Serializable
 :           :           :           :             : !-- java.io.Serializable .................................................................................................... [3]
 :           :           :           :             !-+ Product
 :           :           :           :             : !-- Equals
 :           :           :           :             !-- Object .................................................................................................................. [1]
 :           :           :           !-- shapeless.HList ......................................................................................................... [5]
 :           :           !-- shapeless.HList ......................................................................................................... [5]
 :           !-- shapeless.HList ......................................................................................................... [5]
 !-- shapeless.HList ......................................................................................................... [5]

But the type hierarchy of v2 omitted most information:

-+ com.tribbloids.spike.shapeless_spike.RecordProblem._vs.Out
 !-+ shapeless.HList
   !-+ Serializable
   : !-+ java.io.Serializable
   :   !-- Any
   !-+ Product
   : !-- Equals
   !-- Object

What's the cause of this and how do I summon the type class of Value[_] properly?

tribbloid
  • 4,026
  • 14
  • 64
  • 103
  • How do you print "type hierarchy"? – Dmytro Mitin Jan 07 '21 at 22:41
  • 4
    I used a handcrafted utility: https://github.com/tribbloid/graph-commons/blob/master/src/main/scala/com/tribbloids/graph/commons/util/viz/VizType.scala would you like me to publish it? – tribbloid Jan 07 '21 at 23:57

1 Answers1

4

You lost type refinement. Replace

case class HasValues[T <: HList: TypeTag](v: T) {
  def vs(implicit v: Values[T]): Values[T] = v
}

with

case class HasValues[T <: HList: TypeTag](v: T) {
  def vs(implicit v: Values[T]): Values.Aux[T, v.Out] = v
}

Then both

val v2 = book.values

assert(v2.head == "Benjamin Pierce") 

and

val v2 = book.values(_vs)

assert(v2.head == "Benjamin Pierce") 

compile.

In scala, what is the easiest way to chain functions defined with a type class and of which output type depends on it?

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • Wow, really can't trust automatic type deduction too much. Thanks a lot for pointing it out. Let me verify that shortly – tribbloid Jan 08 '21 at 02:55
  • Just verified, it appears that type deduction doesn't work for either path-dependent types and duck types. In addition, typeTag can be inferred from some (non-local) path-dependent types but not duck types. They probably needs to be addressed in another question – tribbloid Jan 08 '21 at 17:09