2

For "big" codecs, the Scala phase typer takes forever (we're talking minutes) when creating a codec directly from HLists and applying .dropUnits

( ignore(6) ::
  uint(2) ::
  uint(30) ::
  int(4) ::
  int(8) ::
  uint(10) ::
  bool(1) ::
  int(28) ::
  int(27) ::
  uint(12) ::
  uint(9) ::
  uint(6) ::
  int(2) ::
  ignore(3) ::
  bool(1) ::
  uint(19)
).dropUnits.as[SomeBigCaseClass]

And it seems to be way faster to create a codec with ~, and then applying .hlist like such:

( ignore(6) ~
  uint(2) ~
  ...
).hlist.dropUnits.as[SomeBigCaseClass]

But this doesn't seem work.

Could not prove that this.Out can be converted to/from reports.SomeBigCaseClass.
  ).hlist.dropUnits.as[SomeBigCaseClass]
                      ^

The simplest solution I've found, which is good enough for me is omitting Unit values inline.

( (ignore(6) dropLeft 
   uint(2)) :: 
  ...
).as[SomeBigCaseClass]

For codecs with many ignores, this feature would be highly welcome. What am I doing wrong? Am I totally missing the point of .hlist?

kareblak
  • 412
  • 1
  • 3
  • 12
  • It seems that `.hlist` only wraps the codec in a `HList`, and that's ok, but that doesn't really solve the issue of the slow phase typer when `.dropUnits ` on a sized `HList` is invoked. – kareblak Jan 23 '15 at 14:44
  • And also, since `~>` takes precedence over `::`, the parantheses surrounding the `.dropLeft` statement can be ommitted when using the `~>` – kareblak Jan 28 '15 at 09:27

1 Answers1

1

The hlist combinator converts a Codec[A] in to a Codec[A :: HNil]. This is typically used with other combinators, like flatZip, which require an HList based codec.

Repeated use of the ~ operator creates a left-associated Tuple2 based structure. For example, int8 ~ bool ~ int8 has type Codec[((Int, Boolean), Int)]. The latest scodec snapshot, 1.7.0-SNAPSHOT (though not 1.7.0-RC1), has the flattenLeftPairs method, which converts a left associated tuple codec to an equivalent HList codec.

A future version of scodec will have a combinator like ~ but rather than nesting Tuple2 instances, it will create TupleN instances. For example: int8 ~~ bool ~~ int8 would have type Codec[(Int, Boolean, Int)]. This has not been integrated yet though. This has both a performance advantage, by reducing the number of tuples allocated, as well as a convenience advantage, because it allows binding to case classes via widenOpt(SomeBigCaseClass.apply, SomeBigCaseClass.unapply).

Finally, the observed compiler performance problem with dropUnits is indeed a problem with the way that combinator is defined. This has been fixed in scodec-core 1.7.0-SNAPSHOT (not 1.7.0-RC1 though). See https://github.com/scodec/scodec/issues/41.

mpilquist
  • 3,855
  • 21
  • 22
  • Yes, it was rather unobservant of me to fail to the type signature of the `.hlist` before posting the questing. Thanks for the clarifications on the performance issue! - And massive thanks for a great job on the lib, btw. – kareblak Jan 28 '15 at 09:24