Salim Fadhley
Salim Fadhley

Reputation: 8235

How do I define a case class that can accept both List[List[String]] and List[List[Int]] as inputs?

I'm actually trying to make a class that can represent tabular data in columns. This is a simplified model of the code I'm working on intended to illustrate what's puzzling me about scala types.

Let's say I have two types

case class FunnyColumn[T](data:List[T])
case class FunnyTable(items:List[FunnyColumn[Any]])

I want to start adding stuff to my FunnyTable, so here goes. I make a bunch of columns that I might want to add:

val intItem:FunnyColumn[Int] = new FunnyColumn(List(1,2,3))
val stringItem:FunnyColumn[String] = new FunnyColumn(List("A", "B", "C"))
val untypedItem:FunnyColumn[Any] = new FunnyColumn(List(1,2,3))

So far so good:

// works but seems icky, untyped FunnyColumns are not much use to me!
val funny0 = new FunnyTable(List(untypedItem))

I don't really want my columns to be untyped - I want all of my columns to have meaningful types. In this example I've tried (and failed) to add a FunnyColumn[String]:

// Fails because it wants List[FunnyColumn[Any]] but I gave it List[FunnyColumn[Int]]
val funny1 = new FunnyTable(List(intItem))

The problem seems to be because I've defined FunnyTable as accepting literally List[FunnyColumn[Any]], so anything other than a list of Any typed FunnyColumns is bound to fail.

What I want to do is is make it so that I can put any of the variations of FunnyColumn into my FunnyTable, in other words this should also work:

// Fails because it wants List[FunnyColumn[Any]] but I gave it List[FunnyColumn[_ :> String with Int]]
val funny2 = new FunnyTable(List(intItem, stringItem))

How can I redefine my FunnyTable class so that I can store different sub-types of FunnyColumn in it?

Upvotes: 0

Views: 57

Answers (1)

Lee
Lee

Reputation: 144196

You need to make FunnyColumn covariant in T:

case class FunnyColumn[+T](data:List[T])

then FunnyColumn[Any] is a supertype of FunnyColumn[Int].

Upvotes: 1

Related Questions