[Haskell] Haskell as a markup language

oleg at pobox.com oleg at pobox.com
Thu Mar 23 01:27:11 EST 2006

shelarcy wrote:
> SXML can add useful function for macro, like this;
> (define (M:link keyword url)
>    `(a (@ (href ,url)) ,keyword))
> (define (M:link_amazon keyword asin)
>    (M:link keyword
> 	 `("http://www.amazon.co.jp/exec/obidos/ASIN/" ,asin "/someone_id/")))
> (define (M:book keyword urn)
>    `((cite ,(M:link keyword `("urn:isbn:" ,urn)))
> 	" (" ,(M:link_amazon "Amazon" urn) ") "))
> and M:link can use SXML code in its parameter any place;
> ,(M:link `("SXML " (em "can write") " this.") "http://foo.bar/")

HSXML can do all this, too (modulo replacement of the round
parentheses with a pair of square ones).

First, we need `Transparent' SPAN: the grouping of SPAN-level
elements.  TSPAN is an administrative element, which is precisely
equivalent to the sequence of SPAN-level elements in its content.  It
is useful as a return value from a function, if a function needs to
return several SPAN-level elements.  The body of TSPAN has the content
Inline, and the TSPAN element itself is in the Inline context.  TSPAN
is the `inline' analogue of TDIV (which works in the block context).

> newtype TSPAN a = TSPAN a deriving Show
> tspan x = build (as_inline . HW . TSPAN . rev'apppend HNil) nil_inline x
> instance RenderInline b => RenderInline (HW CT_inline (TSPAN b)) where
>     render_inline f (HW (TSPAN body)) = render_inline f body

We can now write

> link url body = a (attr [href (URL url)]) body
> link_amazon asin = 
>    link (concat ["http://www.amazon.co.jp/exec/obidos/ASIN/",asin,
> 		 "/someone_id/"])

which is the close analogue of the SXML code above, only the 'body'
argument is the last one. That seems to be more consistent, although
tastes may vary.

we can write a simple test
> test1 = as_block (p [[link_amazon "123.456" "Amazon book"]])

where the body of the link is a simple string. But we can make
it a bit more complex:

> test2 = as_block (p [[link_amazon "123.456" [[tspan "Amazon" "book"]]]])

In fact, we can use arbitrary _inline_ markup in the body of the link:

> book urn body = as_block $
>     p [[link ("urn:isbn:" ++ urn) body]]
>       "(" [[link_amazon urn [[tspan [[em "Amazon"]] nosp ".com"]]]] ")"
> test3 = book "123.456" "Amazon book"

Again, the body of the 'book' doesn't have to be a simple string. We
can use arbitrary _inline_ markup.

> test4 = book "123.456" 
> 	  [[tspan "HSXML" [[em [[strong "can"]] "write"]] "this," "too."]]

But the following leads to the type error
``Couldn't match `CT_inline' against `CT_block'''

-- testb = book "123.456" 
-- 	  [[h1 "HSXML" [[em [[strong "can"]] "write"]] "this," "too."]]

Indeed, the h1 element is a block rather than inline element.

Rendering of test4 above

> test4h :: IO () = runHTMLRender $ render test4

gives the expected output.

Perhaps we should move to Cafe for further discussion?

More information about the Haskell mailing list