[Haskell-cafe] Of types and constructors; a question of
programming style
Graham Klyne
GK at ninebynine.org
Wed Jul 7 03:56:52 EDT 2004
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
More information about the Haskell-Cafe
mailing list