hughperkins at gmail.com
Sat Jun 30 12:59:45 EDT 2007
Still struggling with this. If anyone has any constructive ideas?
I guess it's not really easy otherwise someone would have come up with a
solution by now ;-)
The issue is the line in makeConstrM'' where we're trying to read (Data a =>
a) from (String). "read" doesnt work, because read needs a to be an
instance of Read, and Data a does not enforce this. Whilst the parent class
can be enforced to be Read, there's nothing to enforce this on the child.
Anyway, took a look at SYB3, which came up with this little bit of code:
class Data a => StringParser a where
parsestring :: String -> a
parsestring x = fst $ head $gread(x)
instance StringParser Int where
parsestring x = read x
instance StringParser String where
parsestring x = read( "\"" ++ x ++ "\"" )
That looks like it should fix the problem with trying to read primitive
child data types: we have a function "parsestring" with various custom
methods for each data type we want to handle. On the face of it, it should
work with any data type that is an instance of DAta, because of the default
Unfortunately (and strangely) not: only data types explicitly added as
instances will work with the default function for the Data class, even if
the datatypes are in fact members of Data, and logically quite capable of
running the default function.
So, we cant use this for our Data a=> String -> a function
There's a bunch of "ext" functions that look potentially useful, but didnt
manage to get any of them to work for this. If anyone has any ideas?
For the moment, the only functions that build are:
return (fromJust $ fst $ head $ gread( "(" ++ (fromJust value) ++ ")" ) )
return ((fromJust . cast) value)
... and neither of these work very well. The second works for strings only,
not for other datatypes. The first just plain doesnt seem to work, for some
reason. (By the way, if anyone knows how to extract debug information from
partially executed functions that would be useful).
Here's testConstrM'' at the moment:
testConstrM'' :: forall a. (Data a,Read a, Show a) => a -> [(String, Maybe
String, DataType,Constr)] -> a
testConstrM'' templateobject fieldvalues = evalState (fromConstrM (do
--value <- gets head
(fieldname,value,datatype,constr) <- gets head
--return (fromJust $ (readConstr datatype value) )
--return (parsestring (fromJust value))
--return (extR (fromJust $ fst $ head $ gread( "(" ++ (fromJust value)
++ ")" ) ) parsestring(fromJust value ) )
return (fromJust $ fst $ head $ gread( "(" ++ (fromJust value) ++ ")"
--return ((fromJust . cast) value)
--case constr of
-- (toConstr(3::Int)) -> return ((fromJust . cast) value)
--IntConstr x -> return ((fromJust . cast) value)
--_ -> return ((fromJust . cast) value)
--return (read_helper fieldname value datatype)
)(toConstr templateobject)) fieldvalues
You feed it a template object with the appropriate type, and an array of
tuples with the fieldname, fieldvalue, datatype and constructor (we only use
the fieldvalue at the moment, so you can leave the others blank).
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Haskell-Cafe