Thanks for all you comments about optional parameters.
Heres the solution I finally adopted.

In HTML, tags nest more HTML. So, one model is to represent tags using
functions. so we might have

small :: Html -> Html
italics :: Html -> Html
paragraph :: Html -> Html

Some Html objects do not have embedded Html, like:

txt :: String -> Html

So one might write

        paragraph (small (italics (txt "Hello, World")))

or

        paragraph . small . italics $ txt "Hello, World"

The problem here is how do you add optional parameters,
like paragraph alignment. 

Adopted solution. Consider an operator:

infixr 7 <<
(<<) :: (HTML a,HTML b) => a -> b -> Html

This reads "nests", so we write

        paragraph << small << italics << "Hello, World"

and read this as 'paragraph nests small, which nests italics, which
nests "Hello, World"'.

Now define the class HTML.

class HTML a where
        html  :: a -> Html

This is a method for translating any object that has
an instance of HTML into a (real) Html object.
The definition over Html itself is trivial.
We can also define HTML over String.

instance HTML Html where
        html a = a

instance HTML String where
        html s  = stringToHtml s 

Our primitive functions have types like:

small     :: [HtmlAttr] -> Html -> Html
italics   :: [HtmlAttr] -> Html -> Html
paragraph :: [HtmlAttr] -> Html -> Html

where HtmlAttr are things like
alignment, etc.
The above example could be written:

        paragraph [] << small [] << italics [] << "Hello, World"

This is ugly, because of the needless []. So we define a new
instance of HTML.

instance (HTML a) => HTML ([HtmlAttr] -> a) where
        html f = html (f [])

This means that anything expecting an HTML will also accept
an object that takes a list of HtmlAttr, and returns an HTML object.
So we can write:

        paragraph << small << italics << "Hello, World"

This works because of the type of (<<), which takes objects
of that are members of the HTML class, and uses the above
"[HtmlAttr] -> a" instance to apply an empty argument list.

We can also write:

        paragraph [align "right"] << small << italics << "Hello, World"

Other tricks, like the restrictions on arguments types, using
classes, could also be used.

Andy


Reply via email to