[web-devel] [Hamlet] CSS size wrapper

Dmitry Kurochkin dmitry.kurochkin at gmail.com
Wed Feb 16 10:49:48 CET 2011

On Wed, 16 Feb 2011 06:25:54 +0200, Michael Snoyman <michael at snoyman.com> wrote:
> It looks good. Instead of the mkSize TH function, if you just define
> an IsString instance, then anyone using OverloadedStrings will be able
> to use string literals. I haven't confirmed this yet, but it might
> even be possible to embed those string literals inside Cassius and GHC
> will still apply fromString appropriately.

I was thinking about it. But as I understand, it would not work unless
you explicitly specify the resulting size type. E.g.

  let s = fromString "100px"

How would GHC know that in this case fromString for PixelSize should be
used? This would force you to add explicit (s :: PixelSize) type. This
is something I want to avoid: Type should be determined from string
constant. Or am I missing something?

> As far as variables inside templates: I personally think that's
> crossing the line again into stuff templates shouldn't be dealing
> with, but I'm open for discussions. Since templates tie in so well
> with Haskell, I just don't think it's worth adding a whole bunch of
> extra code and syntax to make it work.

I understand this is a feature which may be used inappropriately. But
here is mine justification for it:

Consider you want to write a simple Cassius template:

    height: 100px
    width: 100px

#a and #b are related and their width and height should be always the
same. So it makes perfect sense to define (commonSize = $(mkSize
"100px")) and use it instead of literals. I know that commonSize is
needed and used only for that Cassius template, but I have to define it
in an external Haskell module. That makes template not self-contained
and harder to read, pollutes Haskell code with declarations that should
be local to a template. IMO this cases illustrates how local template
variables may be the right solution:

  #{let commonSize = $(mkSize "100px")}
    height: #{commonSize}
    width: #{commonSize}


> Michael
> On Tue, Feb 15, 2011 at 10:55 PM, Dmitry Kurochkin
> <dmitry.kurochkin at gmail.com> wrote:
> > Hi Yesod developers.
> >
> > Attached are two modules to implement CSS size wrappers for Hamlet. It
> > implements several types for different CSS units:
> >
> >  * em - EmSize
> >  * ex - ExSize
> >  * px - PixelSize
> >  * % - PercentageSize
> >  * cm, in, mm, pc, pt - AbsoluteSize
> >
> > You can create them using an mkSize Template Haskell function, e.g.
> >
> >  let size = $(mkSize "100%")
> >
> > All types are instances of Show, Eq, Ord, Num, Fractional and ToCss.
> > This allows you to do math and interpolate it to Hamlet.
> >
> > Ideally, I wanted to have only one type and make an implicit conversion
> > from string literals. But I do not know how to forbid mixing of
> > incompatible units in math (e.g. 10px + 10cm) with a single type. And I
> > do not know how to make implicit conversion from string literals with
> > multiple types.
> >
> > I would appreciate any comments. Including on naming style, type design,
> > API and overall usefulness. Keep in mind that this is the first time I
> > use Template Haskell, so the code may be not optimal and plain ugly
> > (e.g. can we use quasi quotes instead of directly messing with TH?)
> >
> > BTW Michael, one more thing I miss in Hamlet is defining variables in
> > templates. I would prefer to put simple CSS-related constants directly
> > in Cassius instead of a dedicated module. Is it possible to implement?
> >
> > Regards,
> >  Dmitry
> >

More information about the web-devel mailing list