I'm experimenting with singleton types that contain type parameters. I am trying to write a function that will accept both a Witness for that singleton type and a typeclass for its nested type. It's easy to get each one individually (see f1() and f2() below), but I wasn't able to get it to work at the same time:

import shapeless._
import shapeless.labelled.FieldType
import shapeless.syntax.singleton._

sealed trait TC[L]

object TC {
  implicit def intTC = new TC[Int] {}

object Test {
  def f1[VI <: Vector[Int]](value: FieldType[VI, String])(
                            implicit wt: Witness.Aux[VI]) = {}

  def f2[L](value: FieldType[_ <: Vector[L], String])(
            implicit wt: TC[L]) = {}

  def f3[L, M <: Vector[L]](value: FieldType[M, String])(
                            implicit wt: TC[L], witness: Witness.Aux[M]) = {}

  val v = Vector(1,2,3)
  f1(v ->> "foo")    // works
  f2(v ->> "foo")    // works
  f3(v ->> "foo")    // does not work

I am getting

inferred type arguments [Nothing,Test.v.type] do not conform to method f3's type parameter bounds [L,M <: Vector[L]]
[error]   f3(v ->> "foo")

Is there a way to help the compiler infer the inner type and a singleton type at the same time?

  • I guess because the first parameter list does not contain (direct) reference to L, it is inferred as Nothing. Have you tried calling it with f3[Int, v.type]? – Gábor Bakos Dec 31 '17 at 23:08
  • I'm looking for a way for the compiler to infer the types automatically – thesamet Jan 1 '18 at 1:30

The following worked for me. I added an implicit parameter ev that provides evidence that M is a subclass of Vector[L] and binds them together. This is sufficient to prevent the compiler to infer that L is Nothing.

def f3[L, M <: Vector[_]](value: FieldType[M, String])(
                          implicit witness: Witness.Aux[M],
                                   ev: M <:< Vector[L], 
                                   wt: TC[L]) = {}
| improve this answer | |

Your Answer

