garyb / purescript-codec-argonaut

Bi-directional JSON codecs for argonaut
MIT License
38 stars 16 forks source link

Define a `Newtype` helper function #23

Closed JordanMartinez closed 5 years ago

JordanMartinez commented 5 years ago

Right now, this is what I write for newtyped primitives

newtype ID = ID Int

idCodec :: JsonCodec ID
idCodec = dimap (\(ID i) -> i) ID int

I propose adding a helper function that handles this for us:

newtypedCodec :: forall wrapper primitive.
                 Newtype wrapper primitive =>
                 (primitive -> wrapper) ->
                 JsonCodec primitive ->
                 JsonCodec wrapper
newtypedCodec _ = dimap unwrap wrap

Which then allows me to write:

newtype ID = ID Int
derive instance newtypeID :: Newtype ID _

idCodec :: JsonCodec ID
idCodec = newtypedCodec ID int

However, I'm not sure whether this is desirable because it seems to suffer from the same problems that type class codecs have, namely, that changing the newtype's definition will automatically change its decoder, which will fail to decode old versions of that type.

If so, then would this function be worth it purely for documentation purposes?

module Data.Codec.Argonaut.NotImplemented where

newtypedCodec :: forall wrapper primitive.
                 Fail "'newtypedCodec' is not implemented because \
                      \it suffers from the same \
                      \problems as a type class based codec" =>
                 Newtype wrapper primitive =>
                 (primitive -> wrapper) ->
                 JsonCodec primitive ->
                 JsonCodec wrapper
newtypedCodec _ = dimap unwrap wrap
garyb commented 5 years ago

You could just use wrapIso from purescript-profunctor or _Newtype from purescript-profunctor-lenses. :wink:

JordanMartinez commented 5 years ago

Ah... that would do it!