The primary abstraction of this library is Codec, which provides the ability to encode/decode values to/from binary.

There are more general abstractions though, such as Encoder and Decoder. There's also GenCodec which extends
both Encoder and Decoder but allows the types to vary. Given these more general abstractions, a Codec[A] can be
represented as a GenCodec[A, A].

The more general abstractions are important because they allow operations on codecs that would not otherwise be possible.
For example, given a Codec[A], mapping a function A => B over the codec yields a GenCodec[A, B]. Without the
more general abstractions, map is impossible to define (e.g., how would codec.map(f).encode(b) be implemented?).
Given a GenCodec[A, B], the encoding functionality can be ignored by treating it as a Decoder[B], or the encoding
type can be changed via contramap. If after further transformations, the two types to GenCodec are equal, we can
reconstitute a Codec from the GenCodec by calling fuse.

See the codecs package object for pre-defined codecs for many common data types and combinators for building larger
codecs out of smaller ones.

Combinator library for working with binary data.

The primary abstraction of this library is Codec, which provides the ability to encode/decode values to/from binary.

There are more general abstractions though, such as Encoder and Decoder. There's also GenCodec which extends both

`Encoder`

and`Decoder`

but allows the types to vary. Given these more general abstractions, a`Codec[A]`

can be represented as a`GenCodec[A, A]`

.The more general abstractions are important because they allow operations on codecs that would not otherwise be possible. For example, given a

`Codec[A]`

, mapping a function`A => B`

over the codec yields a`GenCodec[A, B]`

. Without the more general abstractions,`map`

is impossible to define (e.g., how would`codec.map(f).encode(b)`

be implemented?). Given a`GenCodec[A, B]`

, the encoding functionality can be ignored by treating it as a`Decoder[B]`

, or the encoding type can be changed via`contramap`

. If after further transformations, the two types to`GenCodec`

are equal, we can reconstitute a`Codec`

from the`GenCodec`

by calling`fuse`

.See the codecs package object for pre-defined codecs for many common data types and combinators for building larger codecs out of smaller ones.

For the categorically minded, note the following:

`Decoder`

is a monad`Encoder`

is a contravariant functor`GenCodec`

is a profunctor`Codec`

is an invariant functor