# Towards monadic bidirectional serialization, a step back

Posted on October 13, 2016

This is written in Literate Haskell.

```
module Bidirectional.Serialization.Two where
import Control.Applicative
import Data.Profunctor
```

## Last episode

I proposed to extend `Codec`

as follows:

```
data Codec_ r w x a = Codec_
parse_ :: r a
{ produce_ :: x -> w ()
, project_ :: x -> a
, }
```

And so on. It was becoming quite sophisticated.

## A step back

Instead fix `produce`

to carry the `a`

type as well.
In a way, this merges `produce_`

and `project_`

in a single
field.

```
data Codec r w x a = Codec
parse :: r a
{ produce :: x -> w a
,
}
instance (Functor r, Functor w)
=> Functor (Codec r w x) where
fmap f codec = Codec
parse = fmap f (parse codec)
{ produce = fmap f . produce codec
,
}
instance (Applicative r, Applicative w)
=> Applicative (Codec r w x) where
pure a = Codec (pure a) (\_ -> pure a)
f <*> a = Codec
parse = parse f <*> parse a
{ produce = \x -> produce f x <*> produce a x
,
}
-- We had lost this one for a moment
instance (Alternative r, Alternative w)
=> Alternative (Codec r w x) where
empty = Codec empty (\_ -> empty)
a <|> a' = Codec
parse = parse a <|> parse a'
{ produce = \x -> produce a x <|> produce a' x
,
}
instance (Functor r, Functor w)
=> Profunctor (Codec r w) where
lmap from codec = codec
produce = produce codec . from
{
}
rmap = fmap
-- Hurray!
instance (Monad r, Monad w)
=> Monad (Codec r w x) where
a >>= f = Codec
parse = parse a >>= parse . f
{ produce = \x ->
, produce a x >>= \a -> produce (f a) x
}
```

Note that constraints are now symmetrical, `(Functor r, Functor w)`

and
`(Monad r, Monad w)`

, instead of `Functor r`

and
`(Monad r, Applicative w)`

, respectively.

In hindsight, the fact that previously we only ever used an `Applicative w`

was suspicious.
We were actually relying on `w ()`

being a monoid.
We might as well turn `w ()`

into a single variable `m`

.

```
-- Simplified Codec_
-- The same instances can be implemented with
-- a Monoid m constraint instead of Applicative w.
data CodecM r m x a = CodecM
parseM :: r a
{ produceM :: x -> m
, }
```

Our `Codec`

subsumes `CodecM`

(and thus `Codec_`

) via the following
encoding:

```
-- We have Monoid m => Applicative (Const m)
codecMToCodec :: CodecM r m x a -> Codec r (Const m) x a
codecMToCodec a = Codec
parse = parseM a
{ produce = Const . produceM a
,
}
codecToCodecM :: Codec r (Const m) x a -> CodecM r m x a
codecToCodecM a = CodecM
parseM = parse a
{ produceM = getConst . produce a
, }
```