Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing an existential data type

I need to write a Serialize instance for the following data type:

data AnyNode = forall n . (Typeable n, Serialize n) => AnyNode n

Serializing this is no problem, but I can't implement deserialization, since the compiler has no way to resolve the specific instance of Serialize n, since the n is isolated from the outer scope.

There's been a related discussion in 2006. I am now wondering whether any sort of solution or a workaround has arrived today.

like image 387
Nikita Volkov Avatar asked Dec 03 '22 22:12

Nikita Volkov


1 Answers

You just tag the type when you serialize, and use a dictionary to untag the type when you deserialize. Here's some pseudocode omitting error checking etc:

serialAnyNode (AnyNode x) = serialize (typeOf n, serialize x)

deserialAnyNode s = case deserialize s of
          (typ,bs) -> case typ of
                         "String" -> AnyNode (deserialize bs :: String)
                         "Int" -> AnyNode (deserialize bs :: Int)
                         ....

Note that you can only deserialize a closed universe of types with your function. With some extra work, you can also deserialize derived types like tuples, maybes and eithers.

But if I were to declare an entirely new type "Gotcha" deriving Typeable and Serialize, deserialAnyNode of course couldn't deal with it without extension.

like image 114
sclv Avatar answered Dec 22 '22 03:12

sclv