
At 10:23 06/07/04 -0400, Scott Turner wrote:
On 2004 July 06 Tuesday 05:35, Graham Klyne wrote:
When I'm designing datatypes for a Haskell program, I sometimes seem to end up with a slightly incoherent mixture of algebraic types and constructors.
example
data Event = Document DocURI Element | Element Name BaseURI Language Children Attributes LiIndex | Subject EndElement | Attribute Name AttributeVal | Text TextVal
At first I was going to say that I would _never_ feel the need to turn a set of constructors into a set of types. But looking again at your example constructors I grasp what you mean by "incoherent". In such cases, what may help is to consider why such disparate entities would be grouped together.
The main reason in this case is that I'm implementing a specification (RDF parser [1]), with a view to keeping the code very close to the specification. Part of my goal is to provide implementation-based feedback on the accuracy of the specification, with clear traceability between the code and the specification document, and also to provide feedback on how easy it is for an implementer to follow the specification. You may notice that some of the events contain references to other specific kinds of events (Document-->Element, Element-->Attribute, etc). My implementation strategy (following the spec) is to create a sequence of Event values that are subsequently analyzed using a Parsec implementation of the grammar. Effectively, this means that I sacrifice some static type checking, and maybe have a little additional dynamic type-labelling overhead, but not too much, I think. BTW, my current solution is with no separate types [2]. #g -- [1] http://www.w3.org/TR/rdf-syntax-grammar/ [2] [[ data Event = Document { base :: String , element :: Event } | Element { name :: ScopedName , base :: String , lang :: String , children :: [Event] , attributes :: [Event] } | EndElement | Attribute { name :: ScopedName , value :: String } | CharData { value :: String } -- Derivative (non-infoset) events: | UriNode { name :: ScopedName } | BlankNode { ident :: String } | PlainLit { value :: String , lang :: String } | TypedLit { value :: String , datatype :: ScopedName } ]] ------------ Graham Klyne For email: http://www.ninebynine.org/#Contact