[web-devel] Setting variables in hamlet forall

Michael Snoyman michael at snoyman.com
Fri Apr 8 12:05:53 CEST 2011


On Fri, Apr 8, 2011 at 2:47 AM, Mark Bradley <barkmadley at gmail.com> wrote:

> On Thu, Apr 7, 2011 at 11:22 PM, Michael Snoyman <michael at snoyman.com>
> wrote:
> > A few points:
> > 1) The cost is twofold: making Hamlet more complex from a user
> perspective,
> > and making the codebase more complex. I'm not a fan of either, unless
> it's
> > really justified.
> > 2) I'm not really certain how your example below works as far as
> > disambiguating Maybe versus [] (i.e., $maybe versus $forall), but if
> we're
> > willing to go in this direction, you already have $let for free:
> > $forall foo <- foos
> >     $forall foobar <- return $ bar foo
> >         #{foobar}
>
> I was really going out there with my suggestions and examples.  The
> real benefit of a unified approach is that you can extend it to apply
> to your custom container types.  Making it pretty similar to foldable
> but with an default behaviour when the data structure is empty.
>
> Actually, forgetting the rest of the discussion here, I think extending
$forall to work on any Foldable is a great idea. Any objections?


> Also if you already have let for free using forall and return, why not
> make a sugared version that compiles down to that?
>
> I haven't looked at your patch yet (thank you btw), but my concern is that
introducing $let, the same way it's used in Haskell, introduces scoping
issues that we don't otherwise have. $forall and $maybe already add a
significant complexity to deal with the bound variable names, but at least
it's bound for only the inner block. With $let, we would want it to be bound
for the remainder of the block most likely. So we'd have two choices:

* Implement a whole bunch of complexity defining and implementing new
scoping rules.
* Have totally different semantics from Haskell.

I'm not sure which approach your patch took. But maybe the problem was with
my choice of name ($let); $with would likely make more sense for the inner
block approach. But even so, I'm still concerned that this is complexity
without enough reward.


> > Here, return would be for the [] instance of Monad. We could also use
> > $maybe, using the Maybe instance of Monad.
> > Michael
> >
> > On Thu, Apr 7, 2011 at 3:46 PM, Mark Bradley <barkmadley at gmail.com>
> wrote:
> >>
> >> On Thu, Apr 7, 2011 at 10:34 PM, Mark Bradley <barkmadley at gmail.com>
> >> wrote:
> >> > On Thu, Apr 7, 2011 at 7:51 PM, Max Cantor <mxcantor at gmail.com>
> wrote:
> >> >> put me in the opposed category.
> >> >>
> >> >> You can just as easily put:
> >> >>  let formId rs = fromMaybe "" $ lookup $...
> >> >>
> >> >> in the haskell function that loads the hamlet file then you just have
> >> >> to put
> >> >>  #{formId rs}
> >> >>
> >> >> in the hamlet.  I think adding syntax should be done only when very
> >> >> necessary.  seems like a very small win here at a big cost.
> >> >
> >> > Where is the cost? Most of the effort would be just glueing together
> >> > some pieces of existing code. Given that there are already two places
> >> > where hamlet does variable binding, adding a third will not hurt it,
> >> > or perhaps a single more expressive form of variable binding is
> >> > required. Something like monadic bind (>>=) where you can bind
> >> > non-monadic values using the identity monad.
> >>
> >> An example:
> >>
> >> $bind row <- rs
> >>    $bind formId <- Identity $ fromMaybe "" $ IntMap.lookup $ getInt
> >> "form_id" row
> >>        <td>#{formId counties}
> >>        <td>#{formId customers}
> >>
> >> It could also be possible to do else cases where it didn't bind:
> >>
> >> -- list bind
> >> $bind row <- rs
> >>    -- identity bind
> >>    $bind formId <- Identity $ fromMaybe "" $ IntMap.lookup $ getInt
> >> "form_id" row
> >>        <td>#{formId counties}
> >>        <td>#{formId customers}
> >>        -- maybe bind
> >>        $bind someValue <- someMaybeValue
> >>            <div>content
> >>        -- maybe value was Nothing
> >>        $nobind
> >>            <div>other content
> >>    -- not possible with identity bind possible place for error/warning
> >>    $nobind
> >>        <div>This should not happen!
> >>
> >> -- empty list
> >> $nobind
> >>    <div>i left my content in my other pants
> >>
> >>
> >>
> >> >
> >> >>
> >> >> yes, if you have a situation where many handlers are calling the same
> >> >> hamlet file, there might be some duplication, but then you can always
> raise
> >> >> the formId function to a top-level function.
> >> >>
> >> >> max
> >> >>
> >> >>  On Apr 7, 2011, at 5:15 PM, Michael Snoyman wrote:
> >> >>
> >> >>> I've been very hesitant about adding more features to Hamlet,
> >> >>> especially ones that are already implemented in Haskell. That's been
> my
> >> >>> reasoning for avoiding any kind of variable definitions until now.
> However,
> >> >>> this does seem like a compelling use case.
> >> >>>
> >> >>> I don't think it would make sense to limit it to foralls: it makes
> as
> >> >>> much sense in maybes, and I think it would be confusing if it only
> applied
> >> >>> in some cases. As for syntax, how about:
> >> >>>
> >> >>> $forall row <- rs
> >> >>>     $let formId = fromMaybe "" $ IntMap.lookup $ getInt "form_id"
> row
> >> >>>     ...
> >> >>>
> >> >>> I'm not 100% sold on this yet, what does everyone else think?
> >> >>>
> >> >>> One last note: I'm probably going to be announcing a feature freeze
> on
> >> >>> Yesod 0.8 *very* soon, and making a beta release to Yackage so that
> people
> >> >>> can test. If you have any last-minute input, now's the time. I'm
> planning on
> >> >>> giving the beta test period about a week, and then releasing to
> Hackage.
> >> >>>
> >> >>> Michael
> >> >>>
> >> >>> On Thu, Apr 7, 2011 at 2:57 AM, <vagif.verdi at gmail.com> wrote:
> >> >>> I noticed a pattern that in hamlet $forall i often retrieve the same
> >> >>> value
> >> >>> from a map, Sometimes 3,4 times.
> >> >>>
> >> >>>    $forall row <- rs
> >> >>>            <td><a href=@{FormR (getInt "form_id" row)}>#{getStr
> >> >>> "form_name"
> >> >>> row}
> >> >>>            <td>#{getStr "docname" row}
> >> >>>            ...
> >> >>>            <td>#{fromMaybe "" (IntMap.lookup (getInt "form_id" row)
> >> >>> counties)}
> >> >>>            <td>#{fromMaybe "" (IntMap.lookup (getInt "form_id" row)
> >> >>> customers)}
> >> >>>
> >> >>> Would it be possible to allow let statement in forall for often used
> >> >>> values ?
> >> >>>
> >> >>> Regards,
> >> >>> Vagif Verdi
> >> >>>
> >> >>> _______________________________________________
> >> >>> web-devel mailing list
> >> >>> web-devel at haskell.org
> >> >>> http://www.haskell.org/mailman/listinfo/web-devel
> >> >>>
> >> >>> _______________________________________________
> >> >>> web-devel mailing list
> >> >>> web-devel at haskell.org
> >> >>> http://www.haskell.org/mailman/listinfo/web-devel
> >> >>
> >> >>
> >> >> _______________________________________________
> >> >> web-devel mailing list
> >> >> web-devel at haskell.org
> >> >> http://www.haskell.org/mailman/listinfo/web-devel
> >> >>
> >> >
> >> >
> >> >
> >> > --
> >> > -barkmadley
> >> > sent from an internet enabled device
> >> >
> >>
> >>
> >>
> >> --
> >> -barkmadley
> >> sent from an internet enabled device
> >
> >
>
>
>
> --
> -barkmadley
> sent from an internet enabled device
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/web-devel/attachments/20110408/1e5aa18e/attachment.htm>


More information about the web-devel mailing list