<br><br><div class="gmail_quote">On Mon, Mar 15, 2010 at 10:04 PM, Gregory Collins <span dir="ltr">&lt;<a href="mailto:greg@gregorycollins.net">greg@gregorycollins.net</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Michael Snoyman &lt;<a href="mailto:michael@snoyman.com">michael@snoyman.com</a>&gt; writes:<br>
<br>
&gt; [F]irstly, I believe your premise is mistaken: we&#39;re not trying to<br>
<div class="im">&gt; &quot;standardize interfaces&quot; for the most part; it&#39;s true that WAI was<br>
&gt; such an approach, but that&#39;s not the focus of this thread.<br>
<br>
</div>If it&#39;s not the focus, it&#39;s a recurring theme, especially in the context<br>
of multiple active efforts in that direction and postings on the list<br>
like this:<br>
<br>
&gt; The Haskell language itself was created to consolidate fragmented<br>
&gt; market of different FP languages. Are we ready to follow our<br>
&gt; &#39;ancestors&#39; and in their spirit do the same when it comes to<br>
&gt; web-framework(s)?<br>
<br>
OK, obviously we&#39;re all on the same &quot;team&quot; here, we&#39;re all drinking the<br>
same kool-aid and there should be plenty of things we can agree upon:<br>
Haskell&#39;s not tremendously popular, there are only so many decent<br>
Haskell hackers, it would be good for us to pool our efforts and work<br>
towards common purposes. And there IS a lot of interest in and support<br>
of the idea of standardizing a web application interface for haskell:<br>
I&#39;ve seen lots of positive chatter and off the top of my head I can<br>
think of at least three on Hackage, yours, Hack, and CGI.<br>
<br>
CGI has a historical reason to exist (it understands the CGI protocol)<br>
but the other two are &quot;just plumbing&quot;. Which is fine!  Plumbing is<br>
great, life would be really horrible without it. But in our case, I<br>
don&#39;t think it&#39;s necessary right now: we don&#39;t have good toilets or<br>
sewers! The marginal utility of producing a WAI/Hack adapter for our<br>
toolkit at this point in time is basically zero: we&#39;re talking about<br>
spending time making it easier to interoperate with *applications that<br>
don&#39;t exist*. In fact, the only ones I can even think of at the moment<br>
are gitit, and MAYBE the Hackage server. Chicken/egg, right?<br>
<div class="im"><br></div></blockquote><div>I don&#39;t think it&#39;s really fair to put CGI in the same category, and the Hack/WAI issue is well documented: Hack is simple, WAI is performant. However, let me address the meat of your claim: even though you don&#39;t see the value, doesn&#39;t mean there is none. I&#39;m able to write an application against the WAI and test it locally with the SimpleServer, then deploy it with CGI. That by itself justifies its existence for me.</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="im">
<br>
&gt; you claim that anyone could write an adapter between two interfaces;<br>
&gt; look at the code for hack-handler-hyena and you&#39;ll understand the<br>
&gt; folly of that sentiment.<br>
<br>
</div>Are you kidding? It&#39;s 164 lines of not-that-hairy code, a full third of<br>
which is a status code lookup table. (OK, I&#39;m going to try to be less<br>
argumentative :) )<br>
<div class="im"><br></div></blockquote><div>It wasn&#39;t the line count I was talking about: it requires spawning a separate thread to convert the Enumerator to a lazy bytestring. </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">
<br>
&gt; But more to the point: because of WAI, we don&#39;t *have* to write the<br>
&gt; adapter,<br>
<br>
</div>This is the &quot;M*N&quot; VS &quot;M+N&quot; argument that the Rack guys make, which would<br>
be a perfectly good argument except that for us (pretty much)<br>
M=N=2. Keep in mind that WSGI (and to a lesser extent, this applies to<br>
rack) was created in the context of a bunch of webserver backends and<br>
more than half a dozen huge Python web toolkits, any one of which<br>
probably had more person-hours invested in it than all of our stuff put<br>
together.<br>
<div class="im"><br>
<br></div></blockquote><div>I don&#39;t really see your point here.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="im">
&gt;  and I don&#39;t see any substantive critiques of the WAI approach. (If<br>
&gt; there are, we can address them by fixing the WAI.)<br>
<br>
</div>...and I just said I was going to try to be less argumentative.<br>
<br>
Your iteratee formulation is wrong, for starters. You picked the one the<br>
current Hyena is using, which Johan is currently in the process of<br>
abandoning because the other way is clearly better -- an explicit<br>
existential variable for the state is not as clean as the other<br>
formulation which pushes that goop down under the lambda, into a<br>
continuation. The Iteratee type from the iteratee library also has a<br>
convenient Monad instance (a big win!). I don&#39;t see that one is possible<br>
here, especially since there&#39;s no way that I can see for your iteratee<br>
to partially consume an input; how can you compose them?<br>
<br>
The Source thing is a little wacky, it should be an Enumerator<br>
instead. Again, the point of these things is that they *compose*;<br>
iteratees, which consume chunks of data, plug into enumerators, which<br>
produce them. So the request body should be an enumerator, and you<br>
process it by providing it an iteratee to read the data; the response<br>
body is an enumerator the user fills out, which plugs into an iteratee<br>
that splats it out the socket.<br>
<br></blockquote><div>So, instead of speaking rhetoric, can you give a concrete example where the Source is *bad*? It has serious benefits over Enumerator, such as the ability to convert (via unsafeInterleaveIO) into a lazy bytestring.</div>
<div><br></div><div>I&#39;m happy to see a better approach, why not give me a datatype for the &quot;obviously better&quot; Enumerator?</div><div><br></div><div>(Hint: releasing no code and using phrases like &quot;clearly better&quot; are not going to win any arguments.)</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Speaking of which, you don&#39;t define an iteratee type, given your<br>
formulation it should be:<br>
<br>
    type Iteratee a = a -&gt; ByteString -&gt; IO (Either a a)<br>
<br>
or more generally<br>
<br>
    type IterateeM m a = a -&gt; ByteString -&gt; m (Either a a)<br>
<br>
which is exactly the Hyena definition.<br> </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
The Status datatype is a mess. The requestHeader field should probably<br>
be a Map instead of an alist. RequestHeader and ResponseHeader don&#39;t<br>
need to have all of those header constructors in the datatype like that;<br>
as a result you have &quot;ReqContentLength&quot; which is awkward to say the<br>
least. Not to mention the fact that web application code should never<br>
have to get its hands dirty dealing with content-lengths for requests<br>
anyways; that should be handled on the enumerator level.<br>
<br></blockquote><div>That just shows a misunderstanding on your part: the content-lengths are *not* handled at the application level, though the information is available to the application. Why would I censor it? And would you care to elaborate on &quot;Status datatype is a mess&quot;?</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Let&#39;s say I use the generic &quot;RequestHeader ByteString&quot; constructor. HTTP<br>
header names are supposed to be case-insensitive, and your Eq instance<br>
does a case-sensitive comparison: &#39;RequestHeader &quot;x-foo&quot; /=<br>
RequestHeader &quot;X-Foo&quot;&#39;, which is wrong; now I can&#39;t use &quot;lookup&quot; to pick<br>
a header out of the alist.<br>
<br></blockquote><div>This is a valid concern. However, my goal in that decision is to keep things as close to the wire as possible. On the wire, x-foo and X-Foo are different. You also are conveniently ignoring all character encoding issues. True, HTTP has a character encoding defined, but do you trust ever web client in the world to respect all this?</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Request has an entry for remoteHost but not remotePort. Request contains<br>
no cookies, query parameters, or POST parameters; I&#39;m supposed to parse<br>
them myself? Users of Java servlets are snickering.<br>
<br></blockquote><div>Yes, you are. You clearly have a misunderstanding about what WAI is about (or are just trying to attack baselessly): it&#39;s meant to represent the raw data.</div><div><br></div><div>(And if anyone wants remotePort for any reason, let me know. I have yet to see a need for it, and no one has asked.) </div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
I&#39;m really not trying to badger you here (honest), I&#39;m being hyperbolic<br>
to make a point: for nearly all of the criticisms I just made, there&#39;s<br>
room for a legitimate disagreement about what is the &quot;best&quot; way to<br>
approach the solution; lots of people wouldn&#39;t want to use iteratees at<br>
all, for instance! I also wouldn&#39;t expect you to rearrange the whole<br>
thing to cater to my whims or anyone else&#39;s, either.<br>
<br>
I think that if we&#39;re going to standardize, one of the following<br>
preconditions has to hold:<br>
<br>
 * the standard is superior on engineering merits, solves concrete<br>
   problems/enables you to get work done, and is agreeable enough to<br>
   enough people that it picks up community momentum by wide<br>
   consensus.<br>
<br>
 * the standard is imposed by fiat, maybe because it comes from the<br>
   language vendor.<br>
<br>
 * the standard comes out of a standardization committee effort which<br>
   hammers out disagreements over a period of time to produce something<br>
   which everyone can stomach --- I&#39;d actually be pretty okay with this<br>
   if it happened, but there&#39;s a reason &quot;design by committee&quot; is a<br>
   perjorative.<br>
<br>
 * the standard comes about as a result of market forces, i.e. blub<br>
   toolkit becomes really popular and a standard emerges because<br>
   everyone wants to interoperate with blub.<br>
<br>
Honestly, I just don&#39;t any of these things happening, not right now.<br>
<div class="im"><br>
<br></div></blockquote><div>Don&#39;t worry, I won&#39;t ask you to join the standardization committee ;).</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">
&gt; Now, let me try to understand your point here: we need standardized<br>
&gt; interfaces for applications to communicate with each other, but we<br>
&gt; can&#39;t do that until we have the low level interfaces hammered out.<br>
<br>
</div>No, you&#39;re misrepresenting me here. What I said is that &quot;we need<br>
pluggable applications that understand how talk to each other&quot;, NOT that<br>
those interfaces should be subject to standardization. There&#39;s a<br>
critical distinction there; you don&#39;t expect Django components to plug<br>
into a Zope app.<br>
<div class="im"><br>
<br>
&gt; On the other hand, you say that it&#39;s premature to try to standardize<br>
&gt; interfaces. And then you make it clear that the use case of many<br>
&gt; people (shared hosting) doesn&#39;t interest you at all; based on previous<br>
&gt; conversations, I believe this means that Snap will have *no* (Fast)CGI<br>
&gt; support.<br>
<br>
</div>I wouldn&#39;t say that&#39;s necessarily true in the long term, although it&#39;s<br>
probably true that I myself am not likely to write it. FastCGI support<br>
is definitely not important to me, but if someone wanted it badly enough<br>
there&#39;s nothing in Snap (as of this moment) which would preclude her<br>
from writing whichever backend she wanted: CGI, WAI, Hack,<br>
whatever. That said, I&#39;d be 100% a-ok with sacrificing CGI support<br>
specifically, because spawning a fresh process every time you want to<br>
service a request is, frankly, dumb and absurdly limiting. It isn&#39;t 1996<br>
anymore.<br>
<div class="im"><br>
<br>
&gt; I think (correct me if I&#39;m wrong) that everyone else here is in<br>
&gt; agreement that the goal should not be to create a great framework that<br>
&gt; will solve everyone&#39;s needs.<br>
<br>
</div>I do agree with this; my point all long has been that no one web library<br>
is going to satisfy everyone any more than one parsing combinator<br>
library or one regular expression library or one database could. I&#39;m<br>
aiming to help create a great framework that satisfies my needs, and if<br>
it works for other people too: great.<br>
<div class="im"><br>
<br>
&gt; The goal should be to create great libraries that can be used<br>
&gt; independently.<br>
<br>
</div>..but not necessarily this, at least not in the broader context of<br>
&quot;people writing web applications&quot;. Obviously I agree in general terms:<br>
self-contained, single-purpose libraries are great. There&#39;s no reason to<br>
have a bunch of competing libraries to parse and output RSS, for<br>
instance.<br>
<br>
A productive *web framework*, on the other hand, by its nature makes a<br>
whole set of &quot;convention over configuration&quot; assumptions about how<br>
requests are handled and routed, how data is accessed, how users are<br>
managed, how to hook into an admin panel, how templates are laid out on<br>
disk, which template system to ship out of the box, how components are<br>
specified, how they talk to each other etc etc etc. I see the future<br>
being a lot like the present, where a heterogeneous collection of<br>
frameworks of varying comprehensiveness and quality provide their own<br>
self-contained ecosystems.<br><br></blockquote><div><br></div><div>Michael </div></div>