[Haskell-cafe] Re: Interesting new user perspective
apfelmus at quantentunnel.de
Sun Oct 12 14:24:55 EDT 2008
Iain Barnett wrote:
> apfelmus wrote:
>>> Martin DeMello wrote:
>>>> is a brilliant example of a common workaday problem found in other
>>>> languages, and solved elegantly in Haskell
>> ... and a solution to a problem that you souldn't have in the first
>> place. I mean, if you want to construct XML or SQL statements, you ought
>> to use an abstract data type that ensures proper nesting etc. and not a
>> simple string.
> Do you have an example of what you mean?
Ah, yes, let me explain.
Tom Moertel's post introduces two use cases, namely generating SQL
statements and HTML documents from a template and some parameters (the
latter are given as String ). Representing all of them as String is
prone to bugs concerning escaping, so he uses a custom string type
instead, namely one that indicates whether it was an SQL statement or
HTML document. So far so good.
Now note that I kept saying "HTML document" or "SQL statement" instead
of "HTML string" or "SQL string" because, and that's my point, why on
earth would you want to think of them as strings in the first place? I
mean, a HTML document is a DOM-tree and an SQL statement is a logical
formula. Just like a Haskell module is a set of function, type and class
definitions and more. Sure, it's nice that all of them can be
represented as a list of Unicode characters, but that's not the primary
way of working with them.
In other words, the typed way of thinking of these things is as abstract
data types "Html" and "Sql" with operations for constructing and
deconstructing them, like for instance
ulist :: Html -> Html -- enclose with a <ul> tag
bold :: Html -> Html -- ~ <b> tag
text :: String -> Html -- a text node
renderHtml :: Html -> String -- pretty print
select :: [TableName] -> WhereClause -> Sql
The Text.Html library offers such an API for Html documents, an example
html << (header (thetitle (text "Web site"))
+++ body (h1 (text "Example")) )
It *goes without saying* that text properly escapes its argument
string when the final Html is printed. And not only does the library
escape things for you, it also ensures that all tags are properly
nested. This can be pushed as far as making type system only accept
completely valid Html documents, for instance by using phantom types like
html :: Html HEAD -> Html BODY -> Html HTML
Peter Thiemann has written a library that does just that
Note that Html may well be implemented as a string internally, what
counts is that the implementation is hidden.
Similar things exist for SQL queries. Daan Leijen has developed a small
domain specific embedded language for database queries, based on the
simple observation that these are basically just list comprehensions.
(Chapter 5 of his thesis)
In a sense, Tom's code is just a minimal abstract data type compared to
a bare-bones String representation, by doing proper escaping.
More information about the Haskell-Cafe