3

I'm just starting out with typelevel's "scodec" library: https://github.com/scodec/scodec

I've found that I've been using the following function a lot:

/**
 * When called on a `Codec[L]` for some `L <: HList`, returns a new codec that encodes/decodes
 * `B :: L` but only returns `L`.  HList equivalent of `~>`.
 * @group hlist
 */
def :~>:[B](codec: Codec[B])(implicit ev: Unit =:= B): Codec[L] = codec.dropLeft(self)

This is useful if I have a case class where I don't want to use every value of the spec:

case class Example(value1: Int, value3)
implicit val exampleCodec: Codec[Example] = (
("value1" | uint8) :: 
("value2" | uint8) :~>: // decode/encode, but dont pass this in when converting from hlist to case class
("value3" | uint8)
).as[Example]

This works well if the value I want to ignore isn't the last one in the hlist. Would anyone know how to change the codec, if instead I wanted my case class to be:

case class Example(value1: Int, value2: Int) // ignore value3

Any help is appreciated - thanks!

Chris Ridmann
  • 2,836
  • 4
  • 18
  • 19

1 Answers1

3

You can just use <~, so instead of this:

implicit val exampleCodec: Codec[Example] = (
  ("value1" | uint8) :: 
  ("value2" | uint8).unit(0) :~>:
  ("value3" | uint8)
).as[Example]

You'd write this:

implicit val exampleCodec: Codec[Example] = (
  ("value1" | uint8) :: 
  ("value3" | uint8) <~
  ("value2" | uint8).unit(0)
).as[Example]

Note that you explicitly have to make the codec a Codec[Unit]—I'm using .unit(0) here for the sake of example.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680
  • Ah nice! Just look for the dropRight I suppose - thanks. – Chris Ridmann Nov 13 '14 at 22:13
  • 1
    In addition to the above technique, you can leave the Unit values in the HList and remove them just before binding to the case class. That is, use :: throughout and then use .dropUnits.as[Example]. – mpilquist Nov 14 '14 at 00:30