<?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: Memoizing polymorphic functions via unmemoization</title>
	<atom:link href="http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization/feed" rel="self" type="application/rss+xml" />
	<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization</link>
	<description>Inspirations &#38; experiments, mainly about denotative/functional programming in Haskell</description>
	<lastBuildDate>Sat, 26 Sep 2020 21:06:12 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.17</generator>
	<item>
		<title>By: The Comonad.Reader &#187; Representing Applicatives</title>
		<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization#comment-776</link>
		<dc:creator><![CDATA[The Comonad.Reader &#187; Representing Applicatives]]></dc:creator>
		<pubDate>Thu, 02 May 2013 14:19:32 +0000</pubDate>
		<guid isPermaLink="false">http://conal.net/blog/?p=203#comment-776</guid>
		<description><![CDATA[&lt;p&gt;[...] working with representable functors tractable. A further tiny taste of Yoneda comes from a nice blog post by Conal Elliott on [...]&lt;/p&gt;
]]></description>
		<content:encoded><![CDATA[<p>[&#8230;] working with representable functors tractable. A further tiny taste of Yoneda comes from a nice blog post by Conal Elliott on [&#8230;]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Edward Kmett</title>
		<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization#comment-775</link>
		<dc:creator><![CDATA[Edward Kmett]]></dc:creator>
		<pubDate>Tue, 08 Feb 2011 12:12:16 +0000</pubDate>
		<guid isPermaLink="false">http://conal.net/blog/?p=203#comment-775</guid>
		<description><![CDATA[&lt;p&gt;BTW- What you call an &quot;unmemoization&quot; is more often consisered a representation of a representable functor by the categorically inclined. Representable functors are isomorphic to (a -&gt; x) for some choice of a. Every right adjoint is representable by its left adjoint applied to unit for instance. You may want to have a look at my representable-functors, adjunctions and representable-tries packages on hackage.&lt;/p&gt;
]]></description>
		<content:encoded><![CDATA[<p>BTW- What you call an &#8220;unmemoization&#8221; is more often consisered a representation of a representable functor by the categorically inclined. Representable functors are isomorphic to (a -&gt; x) for some choice of a. Every right adjoint is representable by its left adjoint applied to unit for instance. You may want to have a look at my representable-functors, adjunctions and representable-tries packages on hackage.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Conal Elliott &#187; Blog Archive &#187; From tries to trees</title>
		<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization#comment-774</link>
		<dc:creator><![CDATA[Conal Elliott &#187; Blog Archive &#187; From tries to trees]]></dc:creator>
		<pubDate>Tue, 01 Feb 2011 18:36:42 +0000</pubDate>
		<guid isPermaLink="false">http://conal.net/blog/?p=203#comment-774</guid>
		<description><![CDATA[&lt;p&gt;[...] Memoizing polymorphic functions via unmemoization [...]&lt;/p&gt;
]]></description>
		<content:encoded><![CDATA[<p>[&#8230;] Memoizing polymorphic functions via unmemoization [&#8230;]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Conal Elliott &#187; Blog Archive &#187; Reverse-engineering length-typed vectors</title>
		<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization#comment-773</link>
		<dc:creator><![CDATA[Conal Elliott &#187; Blog Archive &#187; Reverse-engineering length-typed vectors]]></dc:creator>
		<pubDate>Tue, 01 Feb 2011 18:14:09 +0000</pubDate>
		<guid isPermaLink="false">http://conal.net/blog/?p=203#comment-773</guid>
		<description><![CDATA[&lt;p&gt;[...] Memoizing polymorphic functions via unmemoization [...]&lt;/p&gt;
]]></description>
		<content:encoded><![CDATA[<p>[&#8230;] Memoizing polymorphic functions via unmemoization [&#8230;]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Conal Elliott &#187; Blog Archive &#187; Type-bounded numbers</title>
		<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization#comment-772</link>
		<dc:creator><![CDATA[Conal Elliott &#187; Blog Archive &#187; Type-bounded numbers]]></dc:creator>
		<pubDate>Mon, 31 Jan 2011 01:42:07 +0000</pubDate>
		<guid isPermaLink="false">http://conal.net/blog/?p=203#comment-772</guid>
		<description><![CDATA[&lt;p&gt;[...] Memoizing polymorphic functions via unmemoization [...]&lt;/p&gt;
]]></description>
		<content:encoded><![CDATA[<p>[&#8230;] Memoizing polymorphic functions via unmemoization [&#8230;]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Conal Elliott &#187; Blog Archive &#187; Fixing lists</title>
		<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization#comment-771</link>
		<dc:creator><![CDATA[Conal Elliott &#187; Blog Archive &#187; Fixing lists]]></dc:creator>
		<pubDate>Sun, 30 Jan 2011 18:14:38 +0000</pubDate>
		<guid isPermaLink="false">http://conal.net/blog/?p=203#comment-771</guid>
		<description><![CDATA[&lt;p&gt;[...] Memoizing polymorphic functions via unmemoization [...]&lt;/p&gt;
]]></description>
		<content:encoded><![CDATA[<p>[&#8230;] Memoizing polymorphic functions via unmemoization [&#8230;]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Dan P</title>
		<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization#comment-770</link>
		<dc:creator><![CDATA[Dan P]]></dc:creator>
		<pubDate>Wed, 29 Sep 2010 23:49:42 +0000</pubDate>
		<guid isPermaLink="false">http://conal.net/blog/?p=203#comment-770</guid>
		<description><![CDATA[&lt;p&gt;I had written a lazier version that folded memo, berger and isConst into one function but it&#039;s buggy so I reverted to my first iteration. I expect it&#039;s fixable. So don&#039;t see this as a good version. Just a proof of what&#039;s possible.&lt;/p&gt;

&lt;pre&gt;
type Nat = Integer

(x # f) i = if i==0 then x else f (i-1)

-- Borrowed from http://www.cs.bham.ac.uk/~mhe/papers/exhaustive.hs
berger :: ((Nat -&gt; Bool) -&gt; Bool) -&gt; (Nat -&gt; Bool)
berger p = let b0 = berger (f -&gt; p (False # f))
               b1 = berger (f -&gt; p (True # f))
           in if p (False # b0) then False # b0 else True # b1

-- As if by magic, isConst tests whether its argument is the
-- constant function.
isConst :: ((Nat -&gt; Bool) -&gt; Bool) -&gt; Bool
isConst p = let q f = p f /= pf
                pf = p (const False)
            in not (q (berger q))

data Tree = Tree Tree Tree &#124; Leaf Bool deriving Show

unmemo :: Tree -&gt; (Nat -&gt; Bool) -&gt; Bool
unmemo (Leaf x) a = x
unmemo (Tree x y) a = unmemo (if a 0 then y else x) (a . (1+))

memo :: ((Nat -&gt; Bool) -&gt; Bool) -&gt; Tree
memo p = if isConst p
    then Leaf (p (const False))
    else Tree (memo (p . (False #))) (memo (p . (True #)))

-- id&#039; converts a predicate on Boolean streams to a memoised version

id&#039; :: ((Nat -&gt; Bool) -&gt; Bool) -&gt; ((Nat -&gt; Bool) -&gt; Bool)
id&#039; = unmemo . memo
&lt;/pre&gt;
]]></description>
		<content:encoded><![CDATA[<p>I had written a lazier version that folded memo, berger and isConst into one function but it&#8217;s buggy so I reverted to my first iteration. I expect it&#8217;s fixable. So don&#8217;t see this as a good version. Just a proof of what&#8217;s possible.</p>

<pre>
type Nat = Integer

(x # f) i = if i==0 then x else f (i-1)

-- Borrowed from http://www.cs.bham.ac.uk/~mhe/papers/exhaustive.hs
berger :: ((Nat -&gt; Bool) -&gt; Bool) -&gt; (Nat -&gt; Bool)
berger p = let b0 = berger (f -&gt; p (False # f))
               b1 = berger (f -&gt; p (True # f))
           in if p (False # b0) then False # b0 else True # b1

-- As if by magic, isConst tests whether its argument is the
-- constant function.
isConst :: ((Nat -&gt; Bool) -&gt; Bool) -&gt; Bool
isConst p = let q f = p f /= pf
                pf = p (const False)
            in not (q (berger q))

data Tree = Tree Tree Tree | Leaf Bool deriving Show

unmemo :: Tree -&gt; (Nat -&gt; Bool) -&gt; Bool
unmemo (Leaf x) a = x
unmemo (Tree x y) a = unmemo (if a 0 then y else x) (a . (1+))

memo :: ((Nat -&gt; Bool) -&gt; Bool) -&gt; Tree
memo p = if isConst p
    then Leaf (p (const False))
    else Tree (memo (p . (False #))) (memo (p . (True #)))

-- id' converts a predicate on Boolean streams to a memoised version

id' :: ((Nat -&gt; Bool) -&gt; Bool) -&gt; ((Nat -&gt; Bool) -&gt; Bool)
id' = unmemo . memo
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: conal</title>
		<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization#comment-769</link>
		<dc:creator><![CDATA[conal]]></dc:creator>
		<pubDate>Wed, 29 Sep 2010 23:25:00 +0000</pubDate>
		<guid isPermaLink="false">http://conal.net/blog/?p=203#comment-769</guid>
		<description><![CDATA[&lt;p&gt;Hi Dan.   Try surrounding your code by a pair of html &lt;code&gt;pre&lt;/code&gt; tags.  The preview button ought to show you how it comes out.&lt;/p&gt;

&lt;p&gt;I don&#039;t know what prevents the usual Markdown formatting from working in comments.  More strangely yet, they &lt;em&gt;do&lt;/em&gt; work for me but not for other folks.&lt;/p&gt;
]]></description>
		<content:encoded><![CDATA[<p>Hi Dan.   Try surrounding your code by a pair of html <code>pre</code> tags.  The preview button ought to show you how it comes out.</p>

<p>I don&#8217;t know what prevents the usual Markdown formatting from working in comments.  More strangely yet, they <em>do</em> work for me but not for other folks.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Dan P</title>
		<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization#comment-768</link>
		<dc:creator><![CDATA[Dan P]]></dc:creator>
		<pubDate>Wed, 29 Sep 2010 18:54:58 +0000</pubDate>
		<guid isPermaLink="false">http://conal.net/blog/?p=203#comment-768</guid>
		<description><![CDATA[&lt;blockquote&gt;
  &lt;p&gt;For infinitely large domain values, we must then generate and follow infinite paths.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Actually, that&#039;s not necessarily the case. A total function p of type Stream Bool -&gt; Bool can only examine a finite number of elements of any stream argument it is given. Konig&#039;s lemma tells us that for any p we can find a single finite number that bounds the number of stream elements that are ever examined, no matter what stream argument is given. This means we can use a finite trie for memoisation without doing lub tricks.&lt;/p&gt;

&lt;p&gt;I&#039;d post the code but don&#039;t know what markup to use.&lt;/p&gt;

&lt;p&gt;I&#039;ll be checking out your lub posts in more detail. They answer some questions that have been nagging me for a while.&lt;/p&gt;
]]></description>
		<content:encoded><![CDATA[<blockquote>
  <p>For infinitely large domain values, we must then generate and follow infinite paths.</p>
</blockquote>

<p>Actually, that&#8217;s not necessarily the case. A total function p of type Stream Bool -&gt; Bool can only examine a finite number of elements of any stream argument it is given. Konig&#8217;s lemma tells us that for any p we can find a single finite number that bounds the number of stream elements that are ever examined, no matter what stream argument is given. This means we can use a finite trie for memoisation without doing lub tricks.</p>

<p>I&#8217;d post the code but don&#8217;t know what markup to use.</p>

<p>I&#8217;ll be checking out your lub posts in more detail. They answer some questions that have been nagging me for a while.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: conal</title>
		<link>http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization#comment-767</link>
		<dc:creator><![CDATA[conal]]></dc:creator>
		<pubDate>Tue, 28 Sep 2010 19:35:37 +0000</pubDate>
		<guid isPermaLink="false">http://conal.net/blog/?p=203#comment-767</guid>
		<description><![CDATA[&lt;p&gt;Dan Piponi wrote:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When I wrote my blog article, I thought infinite lists couldn’t possibly be memoized. My argument was that in order to know you were looking at the right entry in the memo table you need equality on infinite lists.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Worse yet, (as you already know) in type-driven functional memoization, we don&#039;t need to compare domain values for equality.
Rather, we decode those values as paths into a type-based memo structure.
For infinitely large domain values, we must then generate and follow infinite paths.&lt;/p&gt;

&lt;p&gt;However, I think my posts on &lt;em&gt;&lt;a href=&quot;http://conal.net/blog/posts/nonstrict-memoization&quot; rel=&quot;nofollow&quot;&gt;Non-strict memoization&lt;/a&gt;&lt;/em&gt; solve this problem, and can make memoization more efficient even with finite lists.
Don&#039;t look (possibly forever) for &quot;&lt;em&gt;the&lt;/em&gt; right entry&quot;.
Instead, given a (possibly infinite) domain value, combine the information (using &lt;code&gt;lub&lt;/code&gt;) associated with a chain of approximations leading up to the domain value in the limit.&lt;/p&gt;

&lt;p&gt;For instance, consider memoizing the function that adds the first 20 elements of a list: &lt;code&gt;f = sum . take 20&lt;/code&gt;.
Using non-strict memoization, the work for all lists with the same first 20 elements can be shared, even for infinite lists.&lt;/p&gt;
]]></description>
		<content:encoded><![CDATA[<p>Dan Piponi wrote:</p>

<blockquote>
  <p>When I wrote my blog article, I thought infinite lists couldn’t possibly be memoized. My argument was that in order to know you were looking at the right entry in the memo table you need equality on infinite lists.</p>
</blockquote>

<p>Worse yet, (as you already know) in type-driven functional memoization, we don&#8217;t need to compare domain values for equality.
Rather, we decode those values as paths into a type-based memo structure.
For infinitely large domain values, we must then generate and follow infinite paths.</p>

<p>However, I think my posts on <em><a href="http://conal.net/blog/posts/nonstrict-memoization" rel="nofollow">Non-strict memoization</a></em> solve this problem, and can make memoization more efficient even with finite lists.
Don&#8217;t look (possibly forever) for &#8220;<em>the</em> right entry&#8221;.
Instead, given a (possibly infinite) domain value, combine the information (using <code>lub</code>) associated with a chain of approximations leading up to the domain value in the limit.</p>

<p>For instance, consider memoizing the function that adds the first 20 elements of a list: <code>f = sum . take 20</code>.
Using non-strict memoization, the work for all lists with the same first 20 elements can be shared, even for infinite lists.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
