1
votes

I originally encountered the behavior below, where code that worked fine when a case class didn't have a companion object would fail to compile when that companion object was defined. I was able to fix it by calling Bar.apply _ instead of simply Bar, but I still don't understand why that is necessary.

I'm trying to use the product-collections library from https://github.com/marklister/product-collections, and it will happily parse a CSV into a case class, but only if that case class has no companion object. This is puzzling, especially since the documentation suggests that the companion object is the ideal place to put additional implicit converters.

I see identical behavior if I define the case class and object in the opposite order, and what I see in the REPL matches my IDE.

What is the effect of defining a companion object to a case class? I would expect it to be precisely nothing, since the companion object (with apply and unapply methods) is already defined by virtue of being a case class.

Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.

scala> import com.github.marklister.collections.io.CsvParser
import com.github.marklister.collections.io.CsvParser

scala> case class Foo(i: Int, d: Double, s: String)
defined class Foo

scala> case class Bar(i: Int, d: Double, s: String); object Bar {}
defined class Bar
defined object Bar

scala> CsvParser(Foo).parse(new java.io.StringReader("1, 2.4,\"hi\"\n3, 8.9,\"bye\""))
res0: Seq[Foo] = List(Foo(1,2.4,hi), Foo(3,8.9,bye))

scala> CsvParser(Bar).parse(new java.io.StringReader("1, 2.4,\"hi\"\n3, 8.9,\"bye\""))
<console>:14: error: overloaded method value apply with alternatives:
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) => F)com.github.marklister.collections.io.CsvParserF22[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) => F)com.github.marklister.collections.io.CsvParserF21[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) => F)com.github.marklister.collections.io.CsvParserF20[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) => F)com.github.marklister.collections.io.CsvParserF19[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) => F)com.github.marklister.collections.io.CsvParserF18[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) => F)com.github.marklister.collections.io.CsvParserF17[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) => F)com.github.marklister.collections.io.CsvParserF16[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) => F)com.github.marklister.collections.io.CsvParserF15[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) => F)com.github.marklister.collections.io.CsvParserF14[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) => F)com.github.marklister.collections.io.CsvParserF13[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) => F)com.github.marklister.collections.io.CsvParserF12[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) => F)com.github.marklister.collections.io.CsvParserF11[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => F)com.github.marklister.collections.io.CsvParserF10[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, T9, F](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => F)com.github.marklister.collections.io.CsvParserF9[T1,T2,T3,T4,T5,T6,T7,T8,T9,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, T8, F](f: (T1, T2, T3, T4, T5, T6, T7, T8) => F)com.github.marklister.collections.io.CsvParserF8[T1,T2,T3,T4,T5,T6,T7,T8,F] <and>
  [T1, T2, T3, T4, T5, T6, T7, F](f: (T1, T2, T3, T4, T5, T6, T7) => F)com.github.marklister.collections.io.CsvParserF7[T1,T2,T3,T4,T5,T6,T7,F] <and>
  [T1, T2, T3, T4, T5, T6, F](f: (T1, T2, T3, T4, T5, T6) => F)com.github.marklister.collections.io.CsvParserF6[T1,T2,T3,T4,T5,T6,F] <and>
  [T1, T2, T3, T4, T5, F](f: (T1, T2, T3, T4, T5) => F)com.github.marklister.collections.io.CsvParserF5[T1,T2,T3,T4,T5,F] <and>
  [T1, T2, T3, T4, F](f: (T1, T2, T3, T4) => F)com.github.marklister.collections.io.CsvParserF4[T1,T2,T3,T4,F] <and>
  [T1, T2, T3, F](f: (T1, T2, T3) => F)com.github.marklister.collections.io.CsvParserF3[T1,T2,T3,F] <and>
  [T1, T2, F](f: (T1, T2) => F)com.github.marklister.collections.io.CsvParserF2[T1,T2,F] <and>
  [T1, F](f: T1 => F)com.github.marklister.collections.io.CsvParserF1[T1,F]
 cannot be applied to (Bar.type)
       CsvParser(Bar).parse(new java.io.StringReader("1, 2.4,\"hi\"\n3, 8.9,\"bye\""))
       ^

scala> CsvParser(Bar.apply _).parse(new java.io.StringReader("1, 2.4,\"hi\"\n3, 8.9,\"bye\""))
res1: Seq[Bar] = List(Bar(1,2.4,hi), Bar(3,8.9,bye))
1

1 Answers

2
votes

The auto generated companion object of your case class Foo will extend (Int, Double, String) => Foo. If you define the companion object yourself for the case class Bar the compiler will no longer automatically add that inheritance relation.

For more information you can take a look at SI-3664.