On Fri, Apr 8, 2011 at 5:03 PM, Max Cantor <mxcantor@gmail.com> wrote:
In an effort to get more type-checked goodness in hamlet, I started using string constants for all my dom IDs and classes.  We're not using the newIdent function because I want control over what the IDs and classes will be named.

I wrote up a little typeclass as such:

class CustomIdentString a where jqVal :: a -> String; idVal :: a -> String

newtype CustomIdentCls = MkCls String
instance CustomIdentString CustomIdentCls where
 jqVal (MkCls s) = "." ++ s; idVal (MkCls s) = s;

newtype CustomIdentId = MkId String
instance CustomIdentString CustomIdentId where
 jqVal (MkId s) = "#" ++ s; idVal (MkId s) = s;

This way, I can refer to divs in javascript using:
$("#{jqVal myId}").foo..

And create the elements in hamlet using
<div ##{idVal myId}> ...

I'm wondering is there a datatype for IDs and Classes that I can use to make the IDs and Classes directly so that:
<div .#{foo myId}> and <div ##{foo myCls}>
would fail to typecheck?

In general, are there any good, safe ways to do this instead of just unwrapping to strings?


It's entirely possible to provide separate datatypes for IDs and classes at the Hamlet level. The problem is, you will either always need to use them in place of String/Text, or we'll need to have a separate typeclass for each and triple the number of instance declarations. My opinion: it's a good idea in theory, but will be more trouble than it's worth in practice.

One recommendation for your existing code: instead of calling jqVal and idVal directly, declare instances of ToHtml and ToJavascript.

Michael