<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Design your functions for partial application</title>
	<atom:link href="http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/</link>
	<description>Bryan O&#039;Sullivan&#039;s blog</description>
	<lastBuildDate>Wed, 08 Feb 2012 06:41:38 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	<item>
		<title>By: Pete</title>
		<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/comment-page-1/#comment-127631</link>
		<dc:creator>Pete</dc:creator>
		<pubDate>Tue, 26 Feb 2008 02:49:21 +0000</pubDate>
		<guid isPermaLink="false">http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/#comment-127631</guid>
		<description>Putting the &#039;target&#039; element last makes them easier to use with higher order state-manipulating functions like &#039;gets&#039; and &#039;modify&#039;. Suppose you have a class of monads with a stack state; then you get mpush = modify . push or in pointy style, mpush x = modify (push x). If you put the target first, you need a flip in both cases.

Just my 2p... (or maybe that should be 1p at today&#039;s exchange rates ;)</description>
		<content:encoded><![CDATA[<p>Putting the &#8216;target&#8217; element last makes them easier to use with higher order state-manipulating functions like &#8216;gets&#8217; and &#8216;modify&#8217;. Suppose you have a class of monads with a stack state; then you get mpush = modify . push or in pointy style, mpush x = modify (push x). If you put the target first, you need a flip in both cases.</p>
<p>Just my 2p&#8230; (or maybe that should be 1p at today&#8217;s exchange rates <img src='http://www.serpentine.com/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Pseudonym</title>
		<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/comment-page-1/#comment-109263</link>
		<dc:creator>Pseudonym</dc:creator>
		<pubDate>Thu, 27 Dec 2007 14:39:16 +0000</pubDate>
		<guid isPermaLink="false">http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/#comment-109263</guid>
		<description>Incidentally, &quot;insert&quot; also follows the least-varying-argument-first rule (what I call &quot;de Bruijn-like ordering&quot;).  After all, it works by induction on the dictionary data structure.  That&#039;s the argument that varies the most.</description>
		<content:encoded><![CDATA[<p>Incidentally, &#8220;insert&#8221; also follows the least-varying-argument-first rule (what I call &#8220;de Bruijn-like ordering&#8221;).  After all, it works by induction on the dictionary data structure.  That&#8217;s the argument that varies the most.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Kenn Knowles</title>
		<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/comment-page-1/#comment-109166</link>
		<dc:creator>Kenn Knowles</dc:creator>
		<pubDate>Thu, 27 Dec 2007 05:03:59 +0000</pubDate>
		<guid isPermaLink="false">http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/#comment-109166</guid>
		<description>OCaml solves this with labeled arguments; do these interact badly with Haskell&#039;s features?  I&#039;m not sure.   Perhaps extensible record encodings allow you to fake it somewhat.</description>
		<content:encoded><![CDATA[<p>OCaml solves this with labeled arguments; do these interact badly with Haskell&#8217;s features?  I&#8217;m not sure.   Perhaps extensible record encodings allow you to fake it somewhat.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tom Moertel</title>
		<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/comment-page-1/#comment-109124</link>
		<dc:creator>Tom Moertel</dc:creator>
		<pubDate>Wed, 26 Dec 2007 23:26:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/#comment-109124</guid>
		<description>Yes, having the map as the final argument to map-&quot;mutating&quot; functions means you&#039;ll have to use a flip now and then to make things foldl&#039; friendly, but is that really too high a price to pay for logical consistency with the other common container interfaces?

In the case of Data.Map&#039;s interface, you&#039;ll almost never want to reuse a partially applied &quot;mutating&quot; function, such as insert; they are effectively one-time-use calls for each map-key-value triple. (The only common exception is to specialize on the value, such as when using (flip (insertWith (+)) 1) to count keys.) Thus every call is likely to require new values for all three arguments, and no argument ordering is going to be optimal for all scenarios. For foldl&#039;-driven scenarios, having the map as the first argument is certainly convenient, but then again it&#039;s pretty easy to define:

ffoldl&#039; f = foldl&#039; (flip f)

and use it whenever you want foldl&#039; semantics but the accumulator as the 2nd argument. To use your scenario, for example:

buildMap = ffoldl&#039; (maybe id (uncurry M.insert)) M.empty . map packageInfo . lines


Cheers! --Tom</description>
		<content:encoded><![CDATA[<p>Yes, having the map as the final argument to map-&#8221;mutating&#8221; functions means you&#8217;ll have to use a flip now and then to make things foldl&#8217; friendly, but is that really too high a price to pay for logical consistency with the other common container interfaces?</p>
<p>In the case of Data.Map&#8217;s interface, you&#8217;ll almost never want to reuse a partially applied &#8220;mutating&#8221; function, such as insert; they are effectively one-time-use calls for each map-key-value triple. (The only common exception is to specialize on the value, such as when using (flip (insertWith (+)) 1) to count keys.) Thus every call is likely to require new values for all three arguments, and no argument ordering is going to be optimal for all scenarios. For foldl&#8217;-driven scenarios, having the map as the first argument is certainly convenient, but then again it&#8217;s pretty easy to define:</p>
<p>ffoldl&#8217; f = foldl&#8217; (flip f)</p>
<p>and use it whenever you want foldl&#8217; semantics but the accumulator as the 2nd argument. To use your scenario, for example:</p>
<p>buildMap = ffoldl&#8217; (maybe id (uncurry M.insert)) M.empty . map packageInfo . lines</p>
<p>Cheers! &#8211;Tom</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Bryan O'Sullivan</title>
		<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/comment-page-1/#comment-109117</link>
		<dc:creator>Bryan O'Sullivan</dc:creator>
		<pubDate>Wed, 26 Dec 2007 22:00:07 +0000</pubDate>
		<guid isPermaLink="false">http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/#comment-109117</guid>
		<description>sclv, fusion doesn&#039;t really have anything to do with the space leakage issue. The problem is that using foldr builds up a big unevaluated chain of thunks like so:

M.insert k1 v1 (M.insert k2 v2 (M.insert k3 v3 ... M.empty)))

Using foldl&#039; instead causes the accumulator to be evaluated to WHNF at each step.</description>
		<content:encoded><![CDATA[<p>sclv, fusion doesn&#8217;t really have anything to do with the space leakage issue. The problem is that using foldr builds up a big unevaluated chain of thunks like so:</p>
<p>M.insert k1 v1 (M.insert k2 v2 (M.insert k3 v3 &#8230; M.empty)))</p>
<p>Using foldl&#8217; instead causes the accumulator to be evaluated to WHNF at each step.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Bryan O'Sullivan</title>
		<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/comment-page-1/#comment-109111</link>
		<dc:creator>Bryan O'Sullivan</dc:creator>
		<pubDate>Wed, 26 Dec 2007 21:02:22 +0000</pubDate>
		<guid isPermaLink="false">http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/#comment-109111</guid>
		<description>Daniel, filter and map follow my general prescription by placing the less frequently varying argument first.

As for your suggested use of insert, it just doesn&#039;t arise much in practice, so why design the API with that in mind?

Regarding your broader point, you&#039;ll notice that where you say there&#039;s no golden rule, I mentioned the element of judgment and experience. I believe we&#039;re actually somewhat in agreement.</description>
		<content:encoded><![CDATA[<p>Daniel, filter and map follow my general prescription by placing the less frequently varying argument first.</p>
<p>As for your suggested use of insert, it just doesn&#8217;t arise much in practice, so why design the API with that in mind?</p>
<p>Regarding your broader point, you&#8217;ll notice that where you say there&#8217;s no golden rule, I mentioned the element of judgment and experience. I believe we&#8217;re actually somewhat in agreement.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: sclv</title>
		<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/comment-page-1/#comment-109110</link>
		<dc:creator>sclv</dc:creator>
		<pubDate>Wed, 26 Dec 2007 20:56:32 +0000</pubDate>
		<guid isPermaLink="false">http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/#comment-109110</guid>
		<description>Foldr should also get you fusion in this case though, no?

In any case, is 

buildMap = foldl&#039; (flip $ uncurry M.insert) M.empty . catMaybes . map packageInfo . lines

really all *that* bad? Especially since catMaybes should get you some fusion as well.</description>
		<content:encoded><![CDATA[<p>Foldr should also get you fusion in this case though, no?</p>
<p>In any case, is </p>
<p>buildMap = foldl&#8217; (flip $ uncurry M.insert) M.empty . catMaybes . map packageInfo . lines</p>
<p>really all *that* bad? Especially since catMaybes should get you some fusion as well.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Daniel Yokomizo</title>
		<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/comment-page-1/#comment-109109</link>
		<dc:creator>Daniel Yokomizo</dc:creator>
		<pubDate>Wed, 26 Dec 2007 20:52:46 +0000</pubDate>
		<guid isPermaLink="false">http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/#comment-109109</guid>
		<description>What if I want to write:

insert k1 v1 $  insert k2 v2 $ insert k3 v3 map

The order for insert is the same used for filter, map &amp; friends, with the container in the end. Searching on the mailing lists there&#039;s quite a few discussions on which order of arguments is the best. Usually the library&#039;s author use cases favor one order while some users prefer a different one. There&#039;s no golden rule, other than following the most usual patterns. For collections it&#039;s usual to place the container last (otherwise it ends different than List).</description>
		<content:encoded><![CDATA[<p>What if I want to write:</p>
<p>insert k1 v1 $  insert k2 v2 $ insert k3 v3 map</p>
<p>The order for insert is the same used for filter, map &amp; friends, with the container in the end. Searching on the mailing lists there&#8217;s quite a few discussions on which order of arguments is the best. Usually the library&#8217;s author use cases favor one order while some users prefer a different one. There&#8217;s no golden rule, other than following the most usual patterns. For collections it&#8217;s usual to place the container last (otherwise it ends different than List).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Bryan O'Sullivan</title>
		<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/comment-page-1/#comment-109105</link>
		<dc:creator>Bryan O'Sullivan</dc:creator>
		<pubDate>Wed, 26 Dec 2007 20:08:19 +0000</pubDate>
		<guid isPermaLink="false">http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/#comment-109105</guid>
		<description>Using foldr to build a map gives you a gigantic space leak. Try it. If you&#039;re lucky, your compiler&#039;s strictness analyser might rescue you from the leak, but I wouldn&#039;t count on it.

Regarding catMaybes, there&#039;s no real difference in the overall shape of the code. It just moves the case analysis to another place in the pipeline.</description>
		<content:encoded><![CDATA[<p>Using foldr to build a map gives you a gigantic space leak. Try it. If you&#8217;re lucky, your compiler&#8217;s strictness analyser might rescue you from the leak, but I wouldn&#8217;t count on it.</p>
<p>Regarding catMaybes, there&#8217;s no real difference in the overall shape of the code. It just moves the case analysis to another place in the pipeline.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: sclv</title>
		<link>http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/comment-page-1/#comment-109104</link>
		<dc:creator>sclv</dc:creator>
		<pubDate>Wed, 26 Dec 2007 20:02:23 +0000</pubDate>
		<guid isPermaLink="false">http://www.serpentine.com/blog/2007/12/26/design-your-functions-for-partial-application/#comment-109104</guid>
		<description>The problem is that lots of folks are going to want the value at the end. Say I want a map with something inserted, but I don&#039;t know what&#039;s inserted until later. Or say I want a foldr, which is a -&gt; b -&gt; b instead if a foldl&#039; which is a -&gt; b-&gt; a ? Then the map as the first argument makes a great deal more sense. Anyway, looks like a job for a catMaybes in the pipeline rather than messing with the insert function at all, and as a bonus, you don&#039;t even need to write a helper function!</description>
		<content:encoded><![CDATA[<p>The problem is that lots of folks are going to want the value at the end. Say I want a map with something inserted, but I don&#8217;t know what&#8217;s inserted until later. Or say I want a foldr, which is a -&gt; b -&gt; b instead if a foldl&#8217; which is a -&gt; b-&gt; a ? Then the map as the first argument makes a great deal more sense. Anyway, looks like a job for a catMaybes in the pipeline rather than messing with the insert function at all, and as a bonus, you don&#8217;t even need to write a helper function!</p>
]]></content:encoded>
	</item>
</channel>
</rss>

