@@ -10,6 +10,7 @@ module Data.Codec.Codec
1010 , PartialCodec , cbuild , assume , covered , (<->) , produceMaybe
1111 -- * Codec combinators
1212 , opt , mapCodec , mapCodecF , mapCodecM
13+ , mapCodec' , comapCodec' , (=.)
1314 )
1415where
1516
@@ -51,8 +52,7 @@ opt (Codec r w) = Codec (optional r) (maybe (pure ()) w)
5152
5253-- | Turn a @`Codec` a@ into a @`Codec` b@ by providing an isomorphism.
5354mapCodec :: Functor fr => (a -> b ) -> (b -> a ) -> Codec fr fw a -> Codec fr fw b
54- mapCodec to from (Codec r w)
55- = Codec (to <$> r) (w . from)
55+ mapCodec = mapCodec'
5656
5757-- | Map a field codec monadically. Useful for error handling but care must be taken to make sure that
5858-- the results are still complementary.
@@ -65,6 +65,32 @@ mapCodecF :: (fr a -> gr a) -> (fw () -> gw ()) -> Codec fr fw a -> Codec gr gw
6565mapCodecF fr fw (Codec r w)
6666 = Codec (fr r) (fw . w)
6767
68+ -- | Independently map the two components of a `Codec'`.
69+ --
70+ -- Generalizes `mapCodec`.
71+ mapCodec' :: Functor fr => (a -> b ) -> (c -> d ) -> Codec' fr fw d a -> Codec' fr fw c b
72+ mapCodec' to from (Codec r w)
73+ = Codec (to <$> r) (w . from)
74+
75+ -- | Map on the `produce` component of a `Codec`.
76+ --
77+ -- @
78+ -- comapCodec' = mapCodec' id
79+ -- @
80+ --
81+ -- But `comapCodec'` does not require a `Functor` constraint.
82+ comapCodec' :: (c -> d ) -> Codec' fr fw d a -> Codec' fr fw c a
83+ comapCodec' from (Codec r w)
84+ = Codec r (w . from)
85+
86+ -- | Infix synonym of `comapCodec'`.
87+ --
88+ -- The symbol mimics a record-like syntax in applicative definitions.
89+ (=.) :: (b -> a' ) -> Codec' fr fw a' a -> Codec' fr fw b a
90+ (=.) = comapCodec'
91+
92+ infixr 5 =.
93+
6894-- | A codec where `a` can be produced from a concrete value of `b` in context `f`,
6995-- and a concrete type of value `b` can always be produced.
7096type ConcreteCodec b f a = Codec (ReaderT b f ) (Const b ) a
0 commit comments