
Hi,
On 27 February 2018 at 13:28, MarLinn
It feels like the underlying problem is the same as with arr: At first there seems to be no way to lift functions into the structure. And we don't want to create two separate types because the whole idea of PU is to make pairs of related picklers and unpicklers composable.
For my own learning, a while ago I implemented a little encoding/decoding library, with the encoders based on contravariant functors. I started with a type which I called `Codec a`, which contained both an encoding and a decoding function. As you did, I quickly found that this makes many typeclass instances impossible. So, like in Tom's reply, I instead added a more generic `Codec' a b` type, which separates the encoding and decoding parameters. I kept `Codec a` as a type synonym for `Codec' a a`. I found the change to make the resulting code much nicer to implement and to use, even though it would be possible for a user to construct an encoder/decoder pair which decodes to a different type than what they started with. In fact, after another round of type parameter introduction (abstracting over the concrete type of the encoded value: bytestrings and bytestring builders in `Codec'`, but type parameters in the yet more general type), I discovered a very natural separation between my "codecs" and combinators for composing them. So in this case, I suppose the moral of the story is that having a type parameter which is both covariant and contravariant is not that useful, and you can always just constrain the type variables to be the same where you need to anyway. The code is here: https://github.com/barrucadu/wheat -- Michael Walker (http://www.barrucadu.co.uk)