简体   繁体   中英

Why Does This Type Constraint Fail for List[Seq[AnyVal or String]]

I am learning about Scala on my own and ran into this. Following on from the excellent answers at Link , suppose I have the following code:

object Example extends App {
  val x = Seq(1, 2, 3)
  val y = Seq("1", "2", "3")

  class Or[A, B]
  implicit def orA[A, B](implicit ev: A): Or[A, B] = new Or
  implicit def orB[A, B](implicit ev: B): Or[A, B] = new Or

  def f1[T](seq: Seq[T])(implicit ev: Or[T =:= Int, T =:= String]) = {
    println(seq)
  }

  f1(Seq(1, 2, 3))
  f1(Seq("1", "2", "3"))
}

This compiles all well and good. But now lets suppose I change the function so that it takes a List of Sequences, instead of just Sequences, and try the following:

object Example extends App {
  val x = Seq(1, 2, 3)
  val y = Seq("1", "2", "3")

  class Or[A, B]
  implicit def orA[A, B](implicit ev: A): Or[A, B] = new Or
  implicit def orB[A, B](implicit ev: B): Or[A, B] = new Or

  def f1[T](seq: List[Seq[T]])(implicit ev: Or[T =:= Int, T =:= String]) = {
    println(seq)
  }

   f1(List(Seq(1, 2, 3), Seq("1", "2", "3")))
}

This however fails. The error message is:

could not find implicit value for parameter ev: conusviz.Example.Or[Any =:= Int,Any =:= String]

My question is, why is this happening? I simply wrapped something the compiler should be able to infer in another type. Is there a way to get this working?

I want to the function to take a List of Int (or Indeed AnyVal) or Strings and still work. I am just a little baffled as to why the compiler is confused. Any explanation along a coded answer would be deeply appreciated from a learning perspective.

Seq(1, 2, 3) has type Seq[Int] , Seq("1", "2", "3") has type Seq[String] . Both Seq[Int] and Seq[String] are subtypes of Seq[Any] . So List(Seq(1, 2, 3), Seq("1", "2", "3")) has type List[Seq[Any]] .

If you want types Seq[Int] and Seq[String] to be preserved then you need not a List but HList

import shapeless.{HList, HNil}
import shapeless.ops.hlist.LiftAll

def f[L <: HList](seq: L)(implicit ev: LiftAll[({type l[T] = Or[T =:= Seq[Int], T =:= Seq[String]]})#l, L]) = {
  println(seq)
}

f(Seq(1, 2, 3) :: Seq("1", "2", "3") :: HNil)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM