<div class="gmail_quote">On Wed, Jun 22, 2011 at 5:23 AM, Jasper Van der Jeugt <span dir="ltr">&lt;<a href="mailto:m@jaspervdj.be">m@jaspervdj.be</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
No, inputList is more applicable for a dynamic list, whereas your list<br>
consists of a fixed set of elements. Your problem can be solved more<br>
easily by creating a simple combinator, as I&#39;ve described on the<br>
stackoverflow thread.<br></blockquote><div><br></div><div>Thanks everyone for the input on this.  What I&#39;ve been thinking, and what I believe I&#39;m seeing in other peoples solutions, is that the fundamental issue in building these types of forms is the interpretation of later parts of the form depends on the interpretation of the earlier parts of the form (e.g., a hidden field giving the length of the list).</div>
<div><br></div><div>Of course applicative doesn&#39;t let you do this as it only lets you form fixed sequences.  The additional power required is precisely what what the monad structure adds.  Specifically, I&#39;m thinking the join operator should let you specify this wonderfully.  Under Yesod&#39;s GForm this would be</div>
<div><br></div><div>join :: GForm s m xml (GForm s m xml a) -&gt; GForm s m xml a</div><div><br></div><div>The idea would be that your outer GForm would read (using the list example) the hidden length parameter and use that to construct and return the (now fixed structure as you know its length) inner GForm using applicative composition like (as in the SO thread).  Apply join and you get a GForm returning a list.</div>
<div><br></div><div>I was wanting to work it out exactly, but that would be several more days as I&#39;m a bit short on time and still not that familiar with the libraries, so I&#39;ll just throw a rough sketch of usage</div>
<div><br></div><div>data Person = Person { age :: Int, name :: String }</div><div><br></div><div>personForm :: Maybe Person -&gt; Form s m Person</div><div>personForm mperson = fieldsToDivs $ Person</div><div>  &lt;$&gt; intField &quot;Age&quot; (fmap age mperson)</div>
<div>  &lt;*&gt; stringField &quot;Name&quot; (fmap name mperson)</div><div><br></div><div>peopleForm :: [Maybe Person] -&gt; Form s m [Person]</div><div>peopleForm mpeople = join $ build</div><div>  &lt;$&gt; fieldsToDivs $ intField &quot;Number&quot; (Just $ length mpeople)</div>
<div>  where</div><div>    build n = traverse personForm $ take n $ mpeople ++ repeat Nothing</div><div><br></div><div>The join should be pretty trivial to implement as GForm is a monad transformer stack.  The only extra bit would be to do the equivalent of wrapping the in inner form in a deeperFormIdent before splicing it in (as I believe is currently being done with with the digest functors list handling design).</div>
<div><br></div><div>Cheers!  -Tyson</div><div><br></div></div>