[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