[Haskell-cafe] How to write a polymorphic serializer?

Viktor Dukhovni ietf-dane at dukhovni.org
Fri Sep 15 07:20:03 UTC 2017


I tried to implement a polymorphic serializer that uses a enclosed
MVar () to serialize an action in an arbitrary IO monad, without
a need for its user to resort to explicit liftIO calls.

So, as a first step I create a typeclass that has a natural default
implementation, and some instances for the Monads of interest that
just use the natural default:

    type Serially m = (MonadIO m) => forall a. IO a -> m a

    class (MonadIO m) => Serializable m where
	serialize :: MVar () -> Serially m
	serialize lock = liftIO . withMVar lock . const

    instance Serializable IO
    instance Serializable (StateT Int IO)
    ...

With this, given:

	foo :: Serially IO -> ... -> IO ()
	foo serially ... = do
	    ...
	    serially $ ...
	    ...

	bar :: Serially (StateT Int IO) -> ... -> StateT Int IO ()
	bar serially ... = do
	    ...
	    serially $ ...
	    ...

I can write:

	lock <- newMVar ()
	foo (serialize lock) ...
	bar (serialize lock)

and the type system figures out the correct version of serialize
for foo's and bar's actual monad.

Is it possible to create a single "serialize lock" closure that
works for both "foo" and "bar"?  Something that works along the
lines of:

	let x = liftIO . withMVar lock . const :: ???
	foo x ...
	bar x ...

If I leave out the "liftIO", then I can of course use:

    x :: forall a. IO a -> IO a

and the "liftIO" can be put explicitly into "foo" and "bar".

    foo x ... = liftIO $ x $ ...
    bar x ... = liftIO $ x $ ...

but is it possible for "x" to both be polymorphic with respect to
its user's monad and at the same time to be a *closure* around some
MVar, and thus not directly a method of a type class.

Of course needing to add an extra "liftI0" here and there is not
onerous, I'm mostly just curious whether I'm missing something that
can hide that boilerplate call in the serializer implementation.

-- 
	Viktor.


More information about the Haskell-Cafe mailing list