new "primitive" instances of Data?
I'm in the process of trying to write generic binary serialization code using the "Scrap Your Boilerplate" method. One bump I've run into is that there are no instances of Data provided for the extended set of numeric types (the stuff in Data.Word, etc.) and it seems to be impossible to hand-write an instance that behaves similarly to the instances for other primitive types. Any ideas for ways around this?
I'm in the process of trying to write generic binary serialization code using the "Scrap Your Boilerplate" method. One bump I've run into is that there are no instances of Data provided for the extended set of numeric types (the stuff in Data.Word, etc.) and it seems to be impossible to hand-write an instance that behaves similarly to the instances for other primitive types. Any ideas for ways around this?
Hi, as a basis for disucssion I propose bit serialisation as in: http://www.cs.vu.nl/boilerplate/testsuite/bits/Main.hs alternatively, the inner workings of normal read and show are inspiring too: http://www.cs.vu.nl/boilerplate/library/Text.hs Your problem seems to refer to instances like the following: (Data.Generics.Basic) -- Another basic datatype instance instance Data Integer where toConstr x = IntegerConstr x fromConstr (IntegerConstr x) = x dataTypeOf _ = IntegerType This GHC 6.2 library instance indeed relies on a CWA as far as basic datatypes are conveniently supported. This is your problem, isn't it. Let me also show the CWA datatype here for convenience: -- | Representation of constructors data Constr = -- The prime case for proper datatype constructors DataConstr ConIndex String Fixity -- Provision for built-in types | IntConstr Int | IntegerConstr Integer | FloatConstr Float | CharConstr Char -- Provision for any type that can be read/shown as string | StringConstr String -- Provision for function types | FunConstr deriving (Show, Typeable) This CWA is there because it allows us to map types to constructors and to go back without inefficient or imprecise conversion. It is basically there for an optimisation. It can be bypassed without problems. That is, there seem to be two ways to handle the problem you have: a) Go via read and show for all the various types such as in: (from Data.Generics.Basics again) -- A basic datatype without a specific branch in Constr instance Data Rational where toConstr x = StringConstr (show x) fromConstr (StringConstr x) = read x dataTypeOf _ = StringType (You can also use other functions that show and read of course.) b) Use type extension via mk? and ext? combinators as in generic read: (from Data.Generics.Text again) gread = readP_to_S gread' where gread' :: Data a => ReadP a gread' = gdefault `extR` scase where -- A specific case for strings scase :: ReadP String scase = readS_to_P reads -- The generic default for gread -- gdefault :: Data a => ReadP a gdefault = ... Please let me know if you need further help. Simon PJ and I have a draft which explains all this but it is too clumsy to release yet :-) All the best, Ralf -- Ralf Laemmel VU & CWI, Amsterdam, The Netherlands http://www.cs.vu.nl/~ralf/
participants (2)
-
Abraham Egnor -
Ralf Laemmel