<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6839602</id><updated>2011-12-15T22:03:26.061-08:00</updated><category term='grammar checking'/><category term='Leibniz equality'/><category term='sized lists'/><category term='definability'/><category term='Heyting algebra'/><category term='static analysis'/><category term='bugs'/><category term='Coq'/><category term='Fomega'/><category term='V=L'/><category term='constructive logic'/><category term='type disequality'/><category term='morphisms'/><category term='nested types'/><category term='flow caml'/><category term='countability'/><category term='kinds'/><category term='impredicativity'/><category term='fuzzy logic'/><category term='termination'/><category term='lightweight static capabilities'/><category term='Simulating Dependent Types with Guarded Algebraic Datatypes'/><category term='C++'/><category term='Haskell'/><category term='Liskov substitutability'/><category term='effects'/><category term='information flow'/><category term='effect inference'/><category term='zero-knowledge proof'/><category term='cardinal numbers'/><category term='_|_'/><category term='CPOs'/><category term='dependent types'/><category term='continuity'/><category term='OOP'/><category term='Dependent ML'/><category term='copious free time'/><category term='parallel or'/><category term='GHC'/><category term='GADTs'/><category term='polymorphism'/><category term='laypeople'/><category term='quotient types'/><category term='refinement types'/><category term='ML'/><category term='referential transparency'/><category term='ordinals'/><category term='conferences'/><title type='text'>Everyone Else is Crazy</title><subtitle type='html'>A blog about typed programming</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.jbapple.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>39</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6839602.post-4085994718741326245</id><published>2008-03-22T14:31:00.000-07:00</published><updated>2008-03-22T14:31:44.534-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='effect inference'/><title type='text'>Region, Effect and Closure Inference, implemented</title><content type='html'>&lt;a href="http://blog.jbapple.com/2007/06/region-effect-and-closure-inference.html"&gt;Last post&lt;/a&gt;

&lt;p&gt;

&lt;a href="http://cs.anu.edu.au/people/Ben.Lippmeier/"&gt;Ben Lippmeier&lt;/a&gt; has posted &lt;a href="http://www.haskell.org/haskellwiki/DDC"&gt;an implementation of his region, effect, and closure inference in a Haskell dialect called The Disciplined Disciple Compiler&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-4085994718741326245?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/4085994718741326245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=4085994718741326245' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/4085994718741326245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/4085994718741326245'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2008/03/region-effect-and-closure-inference.html' title='Region, Effect and Closure Inference, implemented'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-6429016332916682162</id><published>2008-03-16T21:31:00.000-07:00</published><updated>2011-12-15T22:03:26.251-08:00</updated><title type='text'>Types at reddit</title><content type='html'>&lt;a href="http://reddit.com/r/types/"&gt;I have created a subreddit for types.&lt;/a&gt; (Static analysis is also welcome.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-6429016332916682162?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/6429016332916682162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=6429016332916682162' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/6429016332916682162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/6429016332916682162'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2008/03/types-at-reddit.html' title='Types at reddit'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-728777982527328109</id><published>2008-02-22T21:56:00.000-08:00</published><updated>2008-04-08T19:33:27.489-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GADTs'/><category scheme='http://www.blogger.com/atom/ns#' term='nested types'/><title type='text'>Types, named (was: "Name that type!"), plus two more questions</title><content type='html'>Here are the answers to &lt;a href="http://blog.jbapple.com/2008/02/name-that-type-nested-types-edition.html"&gt;the previous quiz&lt;/a&gt;.

&lt;p&gt;

The first datatype holds any factorial number of values. Here it is again, with one small change and a few de-obfuscations:

&lt;pre&gt;

&gt; data FacHelp (f :: * -&gt; *) (y :: *) = 
&gt;      Stop y
&gt;    | More (FacHelp (OneMore f) (f y))
&gt; newtype OneMore (f :: * -&gt; *) (y :: *) = 
&gt;      OneMore (y, f y)
&gt; newtype Identity y = Identity y
&gt; type Factorial y = FacHelp Identity y

&lt;/pre&gt;

&lt;s&gt;

The second is lists of length more than two containing lists of length more than two. This means that no inhabitant contains a prime number of elements. As far as I know, it is unknown whether there is a datatype with every inhabitant containing a prime number of elements. (GADTs can do it, of course, but I'm ignoring those for now, since &lt;a href="http://www.cs.virginia.edu/~jba5b/singleton/Lambda.hs"&gt;they can do anything.&lt;/a&gt; 
(&lt;a href="http://www.haskell.org/pipermail/haskell-cafe/2007-January/021178.html"&gt;mirror&lt;/a&gt;,
&lt;a href="http://thread.gmane.org/gmane.comp.lang.haskell.cafe/18210/focus=18210"&gt;mirror 2&lt;/a&gt;,
&lt;a href="http://www.mail-archive.com/haskell-cafe@haskell.org/msg19411.html"&gt;mirror 3&lt;/a&gt;,
&lt;a href="http://groups.google.com/group/fa.haskell/browse_thread/thread/7741b39b68de7081/16ec8969295ac46c#16ec8969295ac46c"&gt;mirror 4&lt;/a&gt;)

&lt;p&gt;

Here's that datatype again, renamed:

&lt;pre&gt;

&gt; data LongList x = Two x x
&gt;                 | AndAnother x (LongList x)
&gt; data Composite x = Composite (LongList (LongList x))

&lt;/pre&gt;

&lt;/s&gt;

&lt;strong&gt;Update:&lt;/strong&gt;

&lt;br&gt;

&lt;a href="http://www.cs.rutgers.edu/~ccshan/"&gt;Chung-chieh Shan&lt;/a&gt; pointed out to me that I got that datatype wrong. (The other text above is correct, I think.) Anyway, here's his counterexample:

&lt;pre&gt;

&gt; test :: Composite Char
&gt; test = Composite (Two (Two 'a' 'b')
&gt;                       (AndAnother 'c' (Two 'd' 'e')))

&lt;/pre&gt;

This is a correct (I think!) implementation of a container that can't be of a prime size:

&lt;pre&gt;

&gt; data Product f g a = Times (f (g a))
&gt;                    | LeftIncr (Product (OneMore f) g a)
&gt;                    | RightIncr (Product f (OneMore g) a)
&gt; newtype Pair a = Pair (a,a)
&gt; type Comp = Product Pair Pair

&lt;/pre&gt;

&lt;strong&gt;End update&lt;/strong&gt;

&lt;p&gt;

The third datatype uses the type &lt;code&gt;H&lt;/code&gt;, which encodes containers with a square number of elements. &lt;code&gt;H&lt;/code&gt; is based on the idea that the sequence of partial sums of the sequence of odd natural numbers is the same as the sequence of squares. That is, {0, 1, 1+3, 1+3+5, &amp;hellip;} = {0&lt;sup&gt;2&lt;/sup&gt;, 1&lt;sup&gt;2&lt;/sup&gt;, 2&lt;sup&gt;2&lt;/sup&gt;, 3&lt;sup&gt;2&lt;/sup&gt;, &amp;hellip;}

&lt;p&gt;

We can now use &lt;a href="http://en.wikipedia.org/wiki/Lagrange's_four-square_theorem"&gt;Lagrange's four-square theorem&lt;/a&gt; to see that question 3(b) is, strangely, a container that can hold any number of elements. An extension of this by Legendre showed &lt;a href="http://mathworld.wolfram.com/LagrangesFour-SquareTheorem.html"&gt;[cite]&lt;/a&gt; that every number not of the form 4&lt;sup&gt;k&lt;/sup&gt;(8m + 7) is representable by the sum of three squares, and this answers question 3(a).

&lt;p&gt;

Here are both parts again, renamed and cleaned up a bit:

&lt;pre&gt;

&gt; data SqHelp x y = End
&gt;                 | Extra x (SqHelp (y,y,x) y)
&gt; type Square a = SqHelp a a
&gt; data Legendre x = Legendre (Square x) (Square x) (Square x)
&gt; data Lagrange x = Lagrange (Square x) (Legendre x)

&lt;/pre&gt;

Here are two more questions:
&lt;br&gt;
4. Can we write something analogous to 3(a) in a more direct way?
&lt;br&gt;
5.
&lt;pre&gt;

&gt; data M a b = N b
&gt;            | O (M (a,b) a)
&gt; newtype P a = P (M a a)

&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-728777982527328109?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/728777982527328109/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=728777982527328109' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/728777982527328109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/728777982527328109'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2008/02/types-named-was-name-that-type-plus-two.html' title='Types, named (was: &quot;Name that type!&quot;), plus two more questions'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-7473091652753951323</id><published>2008-02-22T03:25:00.000-08:00</published><updated>2008-02-22T09:21:56.362-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GADTs'/><category scheme='http://www.blogger.com/atom/ns#' term='nested types'/><category scheme='http://www.blogger.com/atom/ns#' term='Leibniz equality'/><title type='text'>Name that type! (nested types edition)</title><content type='html'>&lt;!-- &lt;a href="http://www.cs.virginia.edu/~jba5b/singleton/Lambda.hs"&gt;Guarded
algebraic datatypes are strong enough to write datatypes that
represent recursively enumerable sets.&lt;/a&gt; 
(&lt;a href="http://www.haskell.org/pipermail/haskell-cafe/2007-January/021178.html"&gt;mirror&lt;/a&gt;,
&lt;a href="http://thread.gmane.org/gmane.comp.lang.haskell.cafe/18210/focus=18210"&gt;mirror 2&lt;/a&gt;,
&lt;a href="http://www.mail-archive.com/haskell-cafe@haskell.org/msg19411.html"&gt;mirror 3&lt;/a&gt;,
&lt;a href="http://groups.google.se/group/fa.haskell/tree/browse_frm/month/2007-01/b3b8d1c7642923d5?rnum=181&amp;_done=%2Fgroup%2Ffa.haskell%2Fbrowse_frm%2Fmonth%2F2007-01%3F#doc_16ec8969295ac46c"&gt;mirror 4&lt;/a&gt;)
That is, they are are strong as
you could possibly expect. We can even write
datatypes with such strong encodings without GADTs by using Leibniz equality, though we
can't perform all of the operations on them we might hope to
without &lt;a href="http://ecommons.library.cornell.edu/bitstream/1813/5614/1/TR2003-1901.pdf"&gt;first-class
 phantom
  types&lt;/a&gt;. (&lt;a href="http://homepages.inf.ed.ac.uk/jcheney/publications/errata.html#fcpt-tr"&gt;errata&lt;/a&gt;)
(See also &lt;a href="http://homepage.mac.com/pasalic/p2/"&gt;Emir Pasalic&lt;/a&gt;'s
&lt;a href="http://homepage.mac.com/pasalic/p2/papers/thesis.pdf"&gt;thesis&lt;/a&gt;,
Chapter 4: Equality Proofs, p. 72 in your PDF reader, p. 62 in your
printed copy)

&lt;p&gt;

Type equality, whether from Leibniz or GADTs, is not necessary to
write datatypes that enforce useful invariants, however. A simple
example is that of a complete binary tree. A regular binary tree can
be encoded as:
--&gt;

&lt;div style="background-color: #ffb; text-align: center; border: solid 1px; padding: 1em;"&gt;&lt;a href="#quiz"&gt;Jump to the bottom for the quiz&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;

If we want to write a type for binary trees in Haskell, it is easy to do so:

&lt;pre&gt;

&gt; data BinaryTree a = Leaf
&gt;                   | InternalNode (BinaryTree a) a (BinaryTree a)

&lt;/pre&gt;

The structure of the type guarantees certain things about its
inhabitants. For instance, every node has exactly two children. If we
want to guarantee stronger invariants, we can change the shape of the
type. We can write a a type for &lt;dfn&gt;complete&lt;/dfn&gt;
binary tree (that is, binary trees in which every leaf is at the same
depth), as


&lt;pre&gt;

&gt; data CompleteBinaryTree a = Leaves
&gt;                           | NonLeaves a (CompleteBinaryTree (a,a))

&lt;/pre&gt;

The argument in the recursive part of this datatype is not the same as
it is in the declaration. Datatypes with this property are
called &lt;dfn&gt;nested&lt;/dfn&gt; or &lt;dfn&gt;non-regular&lt;/dfn&gt;
or &lt;dfn&gt;heterogeneous&lt;/dfn&gt; or &lt;dfn&gt;non-uniform&lt;/dfn&gt;. We can express
all sorts of invariants with these datatypes. Here's another example:


&lt;pre&gt;

&gt; data AList a b = Nil
&gt;                | Cons a (AList b a)

&lt;/pre&gt;

If we want to manipulate lists that alternate between two
types &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, we could use the
type &lt;code&gt;[Either a b]&lt;/code&gt;, but this doesn't ensure that we don't
have two &lt;code&gt;a&lt;/code&gt;s or two &lt;code&gt;b&lt;/code&gt;s in a row. We could,
instead, use the type &lt;code&gt;[(a,b)]&lt;/code&gt;, but this would only allow
us to create lists of even length. By switching the position of the
parameters in the recursion in &lt;code&gt;AList&lt;/code&gt;, we can represent
alternating lists of any length.


&lt;p&gt;

Here are some other examples of data structure invariants we can ensure with nested types:

&lt;ul&gt;

&lt;li&gt; &lt;a href="http://www.cs.nott.ac.uk/~nhn/TFP2006/Papers/27-GhaniHamanaUustaluVene-CyclicStructuresAsNestedDatatypes.pdf"&gt;Cyclic
    data structures&lt;/a&gt; (&lt;a href="http://cs.ioc.ee/~tarmo/papers/tfp06.pdf"&gt;mirror&lt;/a&gt;)

&lt;li&gt; Many different types of lists with
fast &lt;code&gt;cons&lt;/code&gt;, &lt;code&gt;snoc&lt;/code&gt;, concatenation, and indexing,
including 


&lt;ul&gt;
&lt;li&gt; &lt;a href="http://www.soi.city.ac.uk/~ross/papers/FingerTree.html"&gt;Finger
    trees&lt;/a&gt;
  (&lt;a href="http://www.informatik.uni-bonn.de/~ralf/publications/FingerTrees.pdf"&gt;mirror&lt;/a&gt;, 
&lt;a href="http://web.comlab.ox.ac.uk/oucl/work/ralf.hinze/publications/FingerTrees.pdf"&gt;mirror 2&lt;/a&gt;)
&lt;li&gt;
  &lt;a href="http://www.eecs.usma.edu/webs/people/okasaki/pubs.html#cup98"&gt;Binary random-access lists, catenable lists, and
  catenable deques&lt;/a&gt; 
(&lt;a href="http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf"&gt;earlier version&lt;/a&gt;, 

&lt;a href="http://www.cs.cmu.edu/afs/cs/project/fox/mosaic/papers/cokasaki-thesis.ps"&gt;earlier version mirror&lt;/a&gt;,
&lt;a href="http://citeseer.ist.psu.edu/okasaki98purely.html"&gt;earlier version mirror 2&lt;/a&gt;, 
&lt;a href="http://cybertiggyr.com/gene/amo/amo.html"&gt;notes and answers to exercises&lt;/a&gt;)
&lt;li&gt;
&lt;a href="http://www.informatik.uni-bonn.de/~ralf/publications/DSDesign.ps.gz"&gt;Rightist
  right-perfect trees&lt;/a&gt; (&lt;a href="http://web.comlab.ox.ac.uk/oucl/work/ralf.hinze/publications/DSDesign.ps.gz"&gt;mirror&lt;/a&gt;)
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.informatik.uni-bonn.de/~ralf/publications/WAAAPL99a.ps.gz"&gt;earlier version&lt;/a&gt;, 
&lt;a href="http://citeseer.ist.psu.edu/hinze99manufacturing.html"&gt;earlier version mirror&lt;/a&gt;,

&lt;a href="http://web.comlab.ox.ac.uk/oucl/work/ralf.hinze/publications/WAAAPL99a.ps.gz"&gt;earlier version mirror 2&lt;/a&gt;
&lt;li&gt;
&lt;a href="http://www.informatik.uni-bonn.de/~ralf/publications/IAI-TR-99-5.ps.gz"&gt;even earlier version&lt;/a&gt;,
&lt;a href="http://www.informatik.uni-bonn.de/III/forschung/publikationen/tr/reports/IAI-TR-99-5.ps.gz"&gt;even earlier version mirror&lt;/a&gt;,
&lt;a href="http://web.comlab.ox.ac.uk/oucl/work/ralf.hinze/publications/IAI-TR-99-5.ps.gz"&gt;even earlier version mirror 2&lt;/a&gt;
&lt;/ul&gt;
&lt;/ul&gt;

&lt;li&gt; &lt;a href="http://reddit.com/info/w1oz/comments/cwbrz"&gt;Red-black trees&lt;/a&gt; (&lt;a href="http://www.cs.kent.ac.uk/pubs/2001/1293/index.html"&gt;a paper&lt;/a&gt;,

&lt;a href="http://www.cs.kent.ac.uk/people/staff/smk/redblack/rb.html"&gt;code for that paper&lt;/a&gt;), 
&lt;a href="http://www.haskell.org/pipermail/haskell/2003-April/011693.html"&gt;AVL trees&lt;/a&gt;
(&lt;a href="http://osdir.com/ml/lang.haskell.general/2003-04/msg00120.html"&gt;mirror&lt;/a&gt;,
&lt;a href="http://www.cse.unsw.edu.au/~dons/haskell-1990-2006/msg14064.html"&gt;mirror 2&lt;/a&gt;)

&lt;li&gt; &lt;a href="http://www.eecs.usma.edu/webs/people/okasaki/icfp99.ps"&gt;Square matrices&lt;/a&gt;, 
triangular matrices 
(&lt;a href="http://www.irit.fr/~Ralph.Matthes/works.html"&gt;in various works by Ralph Matthes&lt;/a&gt;), Toeplitz matrices,
  rectangular matrices (see "Manufacturing Datatypes", above)

&lt;li&gt; Efficient-merge heaps (see Okasaki's thesis &amp; book, above), Braun
trees, left-complete trees (see "Manufacturing Datatypes", above)


&lt;li&gt; &lt;a href="http://web.comlab.ox.ac.uk/oucl/work/ralf.hinze/publications/IAI-TR-98-12.ps.gz"&gt;Binomial queues&lt;/a&gt; 
(&lt;a href="http://www.informatik.uni-bonn.de/~ralf/publications/IAI-TR-98-12.ps.gz"&gt;mirror&lt;/a&gt;,
&lt;a href="http://citeseer.ist.psu.edu/hinze98numerical.html"&gt;mirror 2&lt;/a&gt;)

&lt;li&gt; &lt;a href="http://www.informatik.uni-bonn.de/~ralf/publications/GGTries.ps.gz"&gt;Tries&lt;/a&gt; 
(&lt;a href="http://web.comlab.ox.ac.uk/oucl/work/ralf.hinze/publications/GGTries.ps.gz"&gt;mirror&lt;/a&gt;,
&lt;a href="http://citeseer.ist.psu.edu/233124.html"&gt;mirror 2&lt;/a&gt;,
&lt;a href="http://www.informatik.uni-bonn.de/~ralf/publications/GGTries/index.html"&gt;code&lt;/a&gt;,

&lt;a href="http://web.comlab.ox.ac.uk/oucl/work/ralf.hinze/publications/GGTries/index.html"&gt;code mirror&lt;/a&gt;,
&lt;a href="http://www.informatik.uni-bonn.de/~ralf/publications/IAI-TR-98-11.ps.gz"&gt;old version&lt;/a&gt;,
&lt;a href="http://web.comlab.ox.ac.uk/oucl/work/ralf.hinze/publications/IAI-TR-98-11.ps.gz"&gt;old version mirror&lt;/a&gt;)
(See also Okasaki's thesis &amp; book)

&lt;li&gt; &lt;a href="http://citeseer.ist.psu.edu/bird98de.html"&gt;Well-formed terms in the locally-nameless lambda calculus&lt;/a&gt;
(&lt;a href="http://web.comlab.ox.ac.uk/oucl/work/richard.bird/online/BirdPaterson99DeBruijn.pdf"&gt;mirror&lt;/a&gt;)

&lt;/ul&gt;

&lt;a name="quiz"&gt;
Finally, here are 3.5 examples of nested types I haven't seen
elsewhere. See if you can figure out what they do.

&lt;pre&gt;

&gt; data A x y = B (x y)
&gt;            | C (A (D x) (x y))
&gt; newtype D x y = D (y,x y)
&gt; newtype K x = K x
&gt; type QuestionOne = A K
&gt;
&gt; data E x = F x x
&gt;          | G x (E x)
&gt; data QuestionTwo x = Q2 (E (E x))
&gt;
&gt; data H x y = I
&gt;            | J y x x (H (y,x) y)
&gt; type L = H ()
&gt; data QuestionThreePartA x = Q3a (L x) (L x) (L x)
&gt; data QuestionThreePartB x = Q3b (L x) (QuestionThreePartA x)

&lt;/pre&gt;
&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-7473091652753951323?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/7473091652753951323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=7473091652753951323' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/7473091652753951323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/7473091652753951323'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2008/02/name-that-type-nested-types-edition.html' title='Name that type! (nested types edition)'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-8751252559920937913</id><published>2008-02-17T15:02:00.000-08:00</published><updated>2008-02-17T15:59:29.569-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Liskov substitutability'/><category scheme='http://www.blogger.com/atom/ns#' term='Leibniz equality'/><title type='text'>Leibniz and Liskov</title><content type='html'>Leibniz equality of two types &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; is the proposition that in any context, one can be substituted for the other:

&lt;pre&gt;
f a -&gt; f b
&lt;/pre&gt;

A value of this type brings to the value level the proof that two types are equal. The only value of this type is the identity function.

&lt;p&gt;

&lt;a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle"&gt;The Liskov substitution principle&lt;/a&gt; is very similar to Leibniz equality, but only in the contravariant position: If a function takes an argument of type &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;a&lt;/code&gt; is a subtype of &lt;code&gt;b&lt;/code&gt;, then the function must accept an argument of type &lt;code&gt;a&lt;/code&gt;. If &lt;code&gt;f&lt;/code&gt; is a type constructor that uses its argument only negatively, then &lt;code&gt;a&lt;/code&gt; is a subtype of &lt;code&gt;b&lt;/code&gt; if there is a value of type

&lt;pre&gt;
f b -&gt; f a
&lt;/pre&gt;

For example, &lt;code&gt;&amp;lambda;x . x -&gt; b&lt;/code&gt; uses &lt;code&gt;x&lt;/code&gt; negatively, and any &lt;code&gt;b -&gt; b&lt;/code&gt; is also trivially an &lt;code&gt;a -&gt; b&lt;/code&gt; when &lt;code&gt;a&lt;/code&gt; is a subtype of &lt;code&gt;b&lt;/code&gt;. The only value of type &lt;code&gt;f b -&gt; f a&lt;/code&gt; is the &lt;code&gt;cast&lt;/code&gt; function.

&lt;p&gt;

Let's write the kind for type constructors that use their argument negatively as &lt;code&gt;* -(-)-&gt; *&lt;/code&gt; rather than just &lt;code&gt;* -&gt; *&lt;/code&gt;, and the kind for type constructors that use their argument positively as &lt;code&gt;* -(+)-&gt; *&lt;/code&gt;. Then, the following terms should validate our understanding that supertyping is dual to subtyping:

&lt;pre&gt;
dual : &amp;forall; a:* . &amp;forall; b:* . &amp;forall; g: * -(+)-&gt; * . (&amp;forall; f: * -(-)-&gt; * .  f b -&gt; f a) -&gt; g a -&gt; g b
dual |a |b |g less bot = less [&amp;lambda;x:* . g x -&gt; g b] (&amp;lambda;y:g b . y:g b) bot

dual' : &amp;forall; a:* . &amp;forall; b:* . &amp;forall; f: * -(-)-&gt; * . (&amp;forall; g: * -(+)-&gt; * . g a -&gt; g b) -&gt; f b -&gt; f a
dual' |a |b |f more top = more [&amp;lambda;x:* . f x -&gt; f a] (&amp;lambda;y:f a . y:f a) top
&lt;/pre&gt;

So subtyping, like type equality, can be brought to the value domain. I now have two questions:

&lt;ol&gt;
&lt;li&gt;Is there an analogue of &lt;a href="http://research.microsoft.com/~simonpj/papers/ext-f/"&gt;F&lt;sub&gt;C&lt;/sub&gt;&lt;/a&gt; (&lt;a href="http://www.cse.unsw.edu.au/~chak/papers/SCPD07.html"&gt;mirror&lt;/a&gt;) for &lt;a href="http://gatekeeper.dec.com/pub/DEC/SRC/research-reports/abstracts/src-rr-080.html"&gt;F&lt;sub&gt;&amp;lt;:&lt;/sub&gt;&lt;/a&gt;
(&lt;a href="http://lucacardelli.name/Papers/FSub.pdf"&gt;mirror 1&lt;/a&gt;,
&lt;a href="http://research.microsoft.com/Users/luca/Papers/FSub.A4.pdf"&gt;mirror 2&lt;/a&gt;,
&lt;a href="http://citeseer.ist.psu.edu/cardelli91extension.html"&gt;mirror 3&lt;/a&gt;)?

&lt;li&gt;Is there a problem similar to &lt;a href="http://blog.jbapple.com/2007/08/leibniz-equality-decomposition-and.html"&gt;decomposition&lt;/a&gt; for Liskov substitutability?
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-8751252559920937913?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/8751252559920937913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=8751252559920937913' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8751252559920937913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8751252559920937913'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/11/leibniz-and-liskov.html' title='Leibniz and Liskov'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-8391585046753089908</id><published>2008-01-09T23:02:00.000-08:00</published><updated>2008-03-23T16:55:05.270-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GADTs'/><category scheme='http://www.blogger.com/atom/ns#' term='polymorphism'/><category scheme='http://www.blogger.com/atom/ns#' term='lightweight static capabilities'/><category scheme='http://www.blogger.com/atom/ns#' term='refinement types'/><title type='text'>Extra type safety using polymorphic types as first-level refinements</title><content type='html'>&lt;p&gt;

This post is literate Haskell.

&lt;p&gt;

I will demonstrate a new technique for using polytypes as first-level &lt;a href="http://www.cs.ucla.edu/~palsberg/tba/papers/freeman-thesis94.pdf"&gt;refinement types&lt;/a&gt;. (&lt;a href="http://citeseer.ist.psu.edu/225858.html"&gt;mirror&lt;/a&gt;). The goal, as usual, is for types to better express program invariants and ensure programs are safe.

&lt;p&gt;

I'm going to demonstrate using the &lt;code&gt;risers&lt;/code&gt; function, as presented in &lt;a href="http://www.cl.cam.ac.uk/~nx200"&gt;Dana N. Xu&lt;/a&gt;'s &lt;a href="http://research.microsoft.com/Users/simonpj/papers/verify/escH-hw.ps"&gt;ESC/Haskell&lt;/a&gt; (&lt;a href="http://www.cl.cam.ac.uk/~nx200/research/escH-hw.ps"&gt;mirror&lt;/a&gt;), which references &lt;a href="http://www-users.cs.york.ac.uk/~ndm"&gt;Neil Mitchell&lt;/a&gt;'s &lt;a href="http://www-users.cs.york.ac.uk/~ndm/catch/"&gt;Catch&lt;/a&gt;.

&lt;pre&gt;

&gt; {-# OPTIONS -fglasgow-exts #-}
&gt; -- The LANGUAGE pragma is usually a pain for exploratory programming.

&lt;/pre&gt;

&lt;p&gt;

Below are the &lt;code&gt;risers&lt;/code&gt; functions as presented by Xu and
Mitchell. They are the same function, though slightly syntacticly
different. &lt;code&gt;risers&lt;/code&gt; returns the sorted sublists of a
list. 

&lt;p&gt;

Risers has two properties that we are going to discuss:

&lt;ol&gt;
&lt;li&gt; None of the lists in the returned value are empty
&lt;li&gt; If the argument is non-empty, the return value is also non-empty.
&lt;/ol&gt;

&lt;pre&gt;

&gt; risersXu :: (Ord t) =&gt; [t] -&gt; [[t]]
&gt; risersXu [] = []
&gt; risersXu [x] = [[x]]
&gt; risersXu (x:y:etc) =
&gt;     let ss = risersXu (y : etc)
&gt;     in case x &lt;= y of
&gt;          True -&gt; (x : (head ss)) : (tail ss)
&gt;          False -&gt; ([x]) : ss
&gt; 
&gt; risersMitchell :: Ord a =&gt; [a] -&gt; [[a]]
&gt; risersMitchell [] = []
&gt; risersMitchell [x] = [[x]]
&gt; risersMitchell (x:y:etc) = if x &lt;= y
&gt;                            then (x:s):ss
&gt;                            else [x]:(s:ss)
&gt;     where (s:ss) = risersMitchell (y:etc)

&lt;/pre&gt;

&lt;p&gt;

Neither one of these functions is obviously safe. Xu uses head and
tail and ESC/Haskell to create a proof of their safety. The unsafe part
of Mitchell's code is the &lt;code&gt;where&lt;/code&gt; clause, and Mitchell also presents a
tool to prove this safe.

&lt;p&gt;

Our goal will be to write this function in a safe way, with a type
signature that ensures the two properties we expect from the function.
We also aim to do this without having to change the shape of the code,
only the list implementation we are using.

&lt;p&gt;

The present unsafe operations in risersXu and risersMitchell depend on
the second property of the function: non-null inputs generate non-null
outputs. We could write a type for this functions using &lt;a href="http://okmij.org/ftp/Computation/lightweight-dependent-typing.html"&gt;a trusted
library with phantom types for branding&lt;/a&gt; (&lt;a href="http://www.cs.rutgers.edu/~ccshan/capability/lightweight-static-capabilities.pdf"&gt;paper mirror&lt;/a&gt;). This technique (called lightweight static capabilities) can do this
and much else as well, but since clients lose all ability to pattern match
(even in case), risers becomes much more verbose. We could also write
a type signature guaranteeing this by using GADTs.  Without using one
of these, incomplete pattern matching or calling unsafe &lt;code&gt;head&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt;
on the result of the recursive call seems inevitable.

&lt;p&gt;

Here's another way to write the function which does away with the need
for the second property on the recursive call, substituting instead the
need for the first property that no lists in the return value are
empty:

&lt;pre&gt;

&gt; risersAlt :: (Ord t) =&gt; [t] -&gt; [[t]]
&gt; risersAlt [] = []
&gt; risersAlt (x:xs) = 
&gt;     case risersAlt xs of
&gt;       [] -&gt; [[x]]
&gt;       w@((y:ys):z) -&gt; 
&gt;           if x &lt;= y
&gt;           then (x:y:ys):z
&gt;           else ([x]):w
&gt;       ([]:_) -&gt; error "risersAlt"

&lt;/pre&gt;

&lt;p&gt;

The error is never reached.


&lt;p&gt;

Though ensuring the second property with our usual types seems tricky, ensuring the first is not too tough:

&lt;pre&gt;

&gt; type And1 a = (a,[a])
&gt; 
&gt; risersAlt' :: Ord a =&gt; [a] -&gt; [And1 a]
&gt; risersAlt' [] = []
&gt; risersAlt' (x:xs) = 
&gt;     case risersAlt' xs of
&gt;       [] -&gt; [(x,[])]
&gt;       w@(yys:z) -&gt; 
&gt;           if x &lt;= fst yys
&gt;           then (x,fst yys : snd yys):z
&gt;           else (x,[]):w

&lt;/pre&gt;

&lt;p&gt;

It is now much easier to see that risers is safe: There is one pattern
match and one case, and each is simple. No unsafe functions like head
or tail are called. It does have three disadvantages, however.

&lt;p&gt;

First, the second property is still true, but the function type does
not enforce it. This means that any other callers of risers may have
to use incomplete pattern matching or unsafe functions, since they may
not be so easy to transform. It is my intuition that it is not
frequently the case that these functions are tricky to transform, but
&lt;a href="http://neilmitchell.blogspot.com/search/label/catch"&gt;perhaps
Neil Mitchell disagrees&lt;/a&gt;.

&lt;p&gt;

We could fix this by writing another risers function with
type &lt;code&gt;And1 a -&amp;gt; And1 (And1 a)&lt;/code&gt;, but this brings us to
the second problem: &lt;code&gt;And1 a&lt;/code&gt; is not a subtype
of &lt;code&gt;[a]&lt;/code&gt;. This means that callers of our hypothetical other
&lt;code&gt;risers&lt;/code&gt; function (as well as consumers of the output
from &lt;code&gt;risersAlt'&lt;/code&gt;) must explicitly coerce the results back
to lists.

&lt;p&gt;

Finally, if we are wrong about the first property, and risers does
return an empty list for some non-empty input &lt;code&gt;i&lt;/code&gt;, then for any &lt;code&gt;x&lt;/code&gt;,
&lt;code&gt;risers (x:i)&lt;/code&gt; is &lt;code&gt;_|_&lt;/code&gt;, while &lt;code&gt;risersAlt'
(x:i)&lt;/code&gt; is &lt;code&gt;[(x,[])]&lt;/code&gt;. Thus, the equivalence of these
two function definitions depends on the truth of the second property
on the first function, which is something we were trying to get out of
proving in the first place! Of course, if we're interested in the correctness of
&lt;code&gt;risersAlt'&lt;/code&gt;, rather than its equivalence with &lt;code&gt;risersXu&lt;/code&gt; or
&lt;code&gt;risersMitchell&lt;/code&gt;, then it is not to difficult to reason
about. But part of the point of this was to get they compiler to do some
of this reasoning for us, without having to change the shape of the
code.

&lt;p&gt;

Let's write more expressive signatures using something we may have noticed when using GHCi. The only value of type &lt;code&gt;forall a. [a]&lt;/code&gt; (excluding lists of _|_s) is &lt;code&gt;[]&lt;/code&gt;. Every value of type &lt;code&gt;forall a . Maybe a&lt;/code&gt; is &lt;code&gt;Nothing&lt;/code&gt;, and every &lt;code&gt;forall a . Either a Int&lt;/code&gt; has an &lt;code&gt;Int&lt;/code&gt; in &lt;code&gt;Right&lt;/code&gt;. Andrew Koenig &lt;a href="http://www.usenix.org/publications/library/proceedings/vhll/koenig.html"&gt;noticed something similar when learning ML&lt;/a&gt; (&lt;a href="http://web.archive.org/web/20070222202543/http://www.usenix.org/publications/library/proceedings/vhll/full_papers/koenig.a"&gt;archived&lt;/a&gt;), and the &lt;a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Monad-ST.html"&gt;ST monad&lt;/a&gt; operates on a similar principle. (&lt;a href="http://citeseer.ist.psu.edu/launchbury96state.html"&gt;paper with details about ST&lt;/a&gt;, &lt;a href="http://www.cse.ogi.edu/~jl/Papers/stateThreads.ps"&gt;mirror&lt;/a&gt;)

&lt;pre&gt;

&gt; data List a n = Nil n
&gt;               | forall r . a :| (List a r)

&lt;/pre&gt;

&lt;p&gt;

The only values of type &lt;code&gt;forall a . List a n&lt;/code&gt; use the &lt;code&gt;Nil&lt;/code&gt; constructor, and the only values of type &lt;code&gt;forall n . List a n&lt;/code&gt; use the &lt;code&gt;:|&lt;/code&gt; constructor.

&lt;pre&gt;

&gt; infixr :|
&gt; 
&gt; box x = x :| Nil ()
&gt; 
&gt; type NonEmpty a = forall n . List a n
&gt; 
&gt; onebox :: NonEmpty Int
&gt; onebox = box 1
&gt; 
&gt; onebox' :: List Int Dummy
&gt; onebox' = onebox
&gt; 
&gt; data Dummy
&gt; 
&gt; -- This doesn't compile
&gt; -- empty :: NonEmpty a
&gt; -- empty = Nil ()

&lt;/pre&gt;

&lt;p&gt;

&lt;code&gt;NonEmpty a&lt;/code&gt; is a subtype of &lt;code&gt;List a x&lt;code&gt; for all types &lt;code&gt;x&lt;/code&gt;.

&lt;pre&gt;

&gt; data Some fa = forall n . Some (fa n)
&gt; 
&gt; safeHead :: NonEmpty a -&gt; a
&gt; safeHead x = unsafeHead x where
&gt;     unsafeHead (x :| _) = x
&gt; 
&gt; safeTail :: NonEmpty a -&gt; Some (List a)
&gt; safeTail x = unsafeTail x where
&gt;     unsafeTail (_ :| xs) = Some xs

&lt;/pre&gt;

&lt;p&gt;

Unfortunately, we'll be forced to &lt;code&gt;Some&lt;/code&gt; and un-&lt;code&gt;Some&lt;/code&gt; some values, since Haskell does not have first-class existentials, and it takes some thinking to see that &lt;code&gt;safeHead&lt;/code&gt; and &lt;code&gt;safeTail&lt;/code&gt; are actually safe.

&lt;p&gt;

Here is a transformed version of Mitchell's risers:

&lt;pre&gt;

&gt; risersMitchell' :: Ord a =&gt; List a n -&gt; List (NonEmpty a) n
&gt; risersMitchell' (Nil x) = (Nil x)
&gt; risersMitchell' (x :| Nil _) = box (box x)
&gt; risersMitchell' ((x {- :: a -}) :| y :| etc) =
&gt;     case risersMitchell' (y :| etc) {- :: NonEmpty (NonEmpty a) -} of
&gt;       Nil _ -&gt; error "risersMitchell'"
&gt;       s :| ss -&gt; if x &lt;= y
&gt;                  then (x :| s) :| ss
&gt;                  else (box x) :| s :| ss

&lt;/pre&gt;

&lt;p&gt;

Since we can't put the recursive call in a where clause, we must use a case with some dead code. The type annotations are commented out here to show they are not needed, but uncommenting them shows that the recursive call really does return a non-empty lists, and so the &lt;code&gt;Nil&lt;/code&gt; case really is dead code.

&lt;p&gt;

This type signature ensures both of the properties listed when introducing &lt;code&gt;risers&lt;/code&gt;. The key to the non-empty-arguments-produce-non-empty-results property is that the variable &lt;code&gt;n&lt;/code&gt; in the signature is used twice. That means applying &lt;code&gt;risersMitchell'&lt;/code&gt; to a list with a fixed (or existential) type as its second parameter can't produce a &lt;code&gt;NonEmpty&lt;/code&gt; list.

&lt;pre&gt;

&gt; risersXu' :: Ord a =&gt; List a r -&gt; List (NonEmpty a) r
&gt; risersXu' (Nil x) = Nil x
&gt; risersXu' (x :| Nil _) = box (box x)
&gt; risersXu' (((x :: a) :| y :| etc) :: List a r) = 
&gt;     let ss = risersXu' (y :| etc)
&gt;     in case x &lt;= y of
&gt;          True -&gt; case safeTail ss of
&gt;                    Some v -&gt; (x :| (safeHead ss)) :| v
&gt;          False -&gt; (box x) :| ss

&lt;/pre&gt;

&lt;p&gt;

Here we see that the type annotation isn't necessary to infer that &lt;code&gt;risers&lt;/code&gt; applied to a non-empty list returns a non-empty list. The value &lt;code&gt;ss&lt;/code&gt; isn't given a type signature, but we can apply &lt;code&gt;safeHead&lt;/code&gt; and &lt;code&gt;safeTail&lt;/code&gt;. The case matching on &lt;code&gt;safeTail&lt;/code&gt; is the pain of boxing up existentials.

&lt;p&gt;

This is the first version of &lt;code&gt;risers&lt;/code&gt; with a type signature that gives us the original invariant Xu and Mitchell can infer, as well as calling no unsafe functions and containing no incomplete case or let matching. It also returns a list of lists, just like the original function, and has a definition in the same shape.

&lt;p&gt;

With first-class existentials, this would look just like Xu's &lt;code&gt;risers&lt;/code&gt; (modulo built-in syntax for lists). With let binding for polymorphic values, &lt;code&gt;risersMitchell'&lt;/code&gt; would look just like Mitchell's original risers, but be safe by construction. Let binding for polymorphic values would also allow non-trusted implementations of &lt;code&gt;safeTail&lt;/code&gt; and
&lt;code&gt;safeHead&lt;/code&gt; to be actually safe.

&lt;p&gt;

For contrast, here is a GADT implementation of risers:

&lt;pre&gt;

&gt; data GList a n where
&gt;     GNil :: GList a IsNil
&gt;     (:||) :: a -&gt; GList a m -&gt; GList a IsCons
&gt; 
&gt; infixr :||
&gt; 
&gt; data IsNil
&gt; data IsCons
&gt; 
&gt; gbox x = x :|| GNil
&gt; 
&gt; risersMitchellG :: Ord a =&gt; GList a n -&gt; GList (GList a IsCons) n
&gt; risersMitchellG GNil = GNil
&gt; risersMitchellG (c :|| GNil) = gbox $ gbox c
&gt; risersMitchellG (x :|| y :|| etc) =
&gt;     case risersMitchellG (y :|| etc) of
&gt; --    GHC complains, "Inaccessible case alternative: Can't match types `IsCons' and `IsNil'
&gt; --    In the pattern: GNil"
&gt; --    GNil -&gt; error "risers" 
&gt;       s :|| ss -&gt;
&gt;           if x &lt;= y
&gt;           then (x :|| s) :|| ss
&gt;           else (gbox x) :|| s :|| ss

&lt;/pre&gt;

&lt;p&gt;

This is safe and has its safety checked by GHC. It also does not require existentials, though when using this encoding, many other list functions (such as filter) will.

&lt;p&gt;

Now here is a lightweight static capabilities version of risers:

&lt;pre&gt;

&gt; -- module Protected where
&gt; 
&gt; -- Export type constructor, do not export value constructor
&gt; newtype LWSC b a = LWSC_do_not_export_me [a]
&gt; 
&gt; data Full
&gt; type FullList = LWSC Full
&gt; 
&gt; data Any
&gt; 
&gt; lnil :: LWSC Any a
&gt; lnil = LWSC_do_not_export_me []
&gt; 
&gt; lcons :: a -&gt; LWSC b a -&gt; FullList a
&gt; lcons x (LWSC_do_not_export_me xs) = LWSC_do_not_export_me (x:xs) 
&gt; 
&gt; lwhead :: FullList a -&gt; a
&gt; lwhead (LWSC_do_not_export_me x) = head x
&gt; 
&gt; data Some' f n = forall a . Some' (f a n)
&gt; 
&gt; lwtail :: FullList a -&gt; Some' LWSC a
&gt; lwtail (LWSC_do_not_export_me a) = Some' (LWSC_do_not_export_me (tail a))
&gt; 
&gt; deal :: LWSC b a -&gt; LWSC Any c -&gt; (FullList a -&gt; FullList c) -&gt; LWSC b c
&gt; deal (LWSC_do_not_export_me []) _ _ = LWSC_do_not_export_me []
&gt; deal (LWSC_do_not_export_me x) _ f = 
&gt;     case f (LWSC_do_not_export_me x) of
&gt;       LWSC_do_not_export_me z -&gt; LWSC_do_not_export_me z
&gt; 
&gt; nullcase :: LWSC b a -&gt; c -&gt; (FullList a -&gt; c) -&gt; c
&gt; nullcase (LWSC_do_not_export_me []) z _ = z
&gt; nullcase (LWSC_do_not_export_me x) _ f = f (LWSC_do_not_export_me x)
&gt; 
&gt; -- module Risers where
&gt; 
&gt; lbox x = lcons x lnil
&gt; 
&gt; risersXuLW :: Ord a =&gt; LWSC b a -&gt; LWSC b (FullList a)
&gt; risersXuLW x = 
&gt;     deal x
&gt;     lnil
&gt;     (\z -&gt; let x = lwhead z
&gt;            in case lwtail z of
&gt;                 Some' rest -&gt; 
&gt;                     nullcase rest
&gt;                     (lbox (lbox x))
&gt;                     (\yetc -&gt; 
&gt;                          let y = lwhead yetc
&gt;                              etc = lwtail yetc
&gt;                              ss = risersXuLW yetc
&gt;                          in if x &lt;= y
&gt;                             then case lwtail ss of
&gt;                                    Some' v -&gt; lcons (lcons x $ lwhead ss) v
&gt;                             else lcons (lbox x) ss))

&lt;/pre&gt;

&lt;p&gt;

There is a good bit of code that must go in the protected module, including two different functions for case dispatch. These functions are used instead of pattern matching, and make the definition of risers much more verbose, though I may not have written it with all the &lt;a href="http://arcanux.org/lambdacats/type-woes.jpg"&gt;oleg-magic&lt;/a&gt; possible to make it more usable.

&lt;p&gt;

Out of the three, I think GADTs are still the winning approach, but it's fun to explore this new idea, especially since Haskell doesn't have traditional subtyping.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-8391585046753089908?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/8391585046753089908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=8391585046753089908' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8391585046753089908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8391585046753089908'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2008/01/extra-type-safety-using-polymorphic.html' title='Extra type safety using polymorphic types as first-level refinements'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-3028825677574535690</id><published>2008-01-06T17:36:00.000-08:00</published><updated>2008-01-06T17:47:51.397-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conferences'/><title type='text'>POPL 2008 and affiliated events</title><content type='html'>This week is &lt;a href="http://www.cs.ucsd.edu/popl/08/#AffiliatedEvents"&gt;POPL and affiliated events&lt;/a&gt;. I'll be at the first and third days of &lt;a href="http://www1.cs.uic.edu/vmcai08/index.php"&gt;VMCAI&lt;/a&gt;, &lt;a href="http://www.cis.upenn.edu/~plclub/popl08-tutorial/"&gt;the Coq tutorial&lt;/a&gt;, and POPL itself. Unfortunately, I'll have to miss &lt;a href="http://www.program-transformation.org/PEPM08"&gt;PEPM&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-3028825677574535690?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/3028825677574535690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=3028825677574535690' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/3028825677574535690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/3028825677574535690'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2008/01/popl-2008-and-affiliated-events.html' title='POPL 2008 and affiliated events'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-8473302617671836402</id><published>2007-12-27T21:15:00.000-08:00</published><updated>2007-12-27T21:17:09.264-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dependent types'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>A common language for dependently-typed programming?</title><content type='html'>&lt;a href="http://research.microsoft.com/~simonpj/papers/history-of-haskell/index.htm"&gt;The Haskell project was begun in order to unify &amp;quot;more than a dozen non-strict, purely functional programming languages&amp;quot;.&lt;/a&gt; (&lt;a href="http://portal.acm.org/ft_gateway.cfm?id=1238856&amp;type=pdf"&gt;mirror&lt;/a&gt;) We are rapidly approaching that many viable choices for programming with dependent types.

&lt;ol&gt;
&lt;li&gt;
&lt;a href="http://www.e-pig.org/"&gt;Epigram&lt;/a&gt;

&lt;li&gt;
&lt;a href="http://www.ats-lang.org/"&gt;ATS&lt;/a&gt; (successor to &lt;a href="http://cs-www.bu.edu/~hwxi/DML/DML.html"&gt;Dependent ML&lt;/a&gt; and &lt;a href="http://www.cs.bu.edu/~hwxi/Xanadu/Xanadu.html"&gt;Xanadu&lt;/a&gt;)

&lt;li&gt;
&lt;a href="http://unit.aist.go.jp/cvs/Agda/"&gt;Agda&lt;/a&gt; (successor to &lt;a href="http://www.cs.chalmers.se/%7Eaugustss/cayenne/"&gt;Cayenne&lt;/a&gt;)

&lt;li&gt;
&lt;a href="http://web.cecs.pdx.edu/~sheard/Omega/index.html"&gt;&amp;Omega;mega&lt;/a&gt;

&lt;li&gt;
&lt;a href="http://www.nuprl.org/"&gt;NuPrl&lt;/a&gt;

&lt;li&gt;
&lt;a href="http://twelf.plparty.org/"&gt;Twelf&lt;/a&gt;

&lt;li&gt;
&lt;a href="http://isabelle.in.tum.de/"&gt;Isabelle&lt;/a&gt;

&lt;li&gt;
&lt;a href="http://coq.inria.fr/"&gt;Coq&lt;/a&gt;



&lt;li&gt;
&lt;a href="http://cs-www.cs.yale.edu/homes/delphin/"&gt;Delphin&lt;/a&gt;



&lt;li&gt;
&lt;a href="http://www.metaocaml.org/concoqtion/"&gt;Concoqtion&lt;/a&gt;



&lt;li&gt;
&lt;a href="http://www.aldor.org/"&gt;Aldor&lt;/a&gt;



&lt;li&gt;
&lt;a href="http://www.guru-lang.org/"&gt;Guru&lt;/a&gt; (successor to &lt;a href="http://cl.cse.wustl.edu/papers/rsp1-tech.pdf"&gt;RSP1&lt;/a&gt;)


&lt;/ol&gt;

And now, a list of caveats about the above list:

&lt;ul&gt;
&lt;li&gt;
Some of the items on this list are theorem provers first and dependently-typed programming languages second. &lt;a href="http://www.cs.berkeley.edu/~adamc/papers/PositionPLPV06/"&gt;Adam Chlipala argues that this is not such a problem for Coq&lt;/a&gt;.

&lt;li&gt;
This list does not include several languages that are new or new variants (&lt;a href="http://www.seas.upenn.edu/~sweirich/papers/tfp07.pdf"&gt;PIE&lt;/a&gt;, &lt;a href="http://matita.cs.unibo.it/"&gt;Matita&lt;/a&gt;), not checked at compile-time (&lt;a href="http://sage.soe.ucsc.edu/"&gt;Sage&lt;/a&gt;), or not actively maintained (&lt;a href="http://www.cs.ru.nl/~freek/digimath/bycategory.html#tacticprover"&gt;most proof assistants&lt;/a&gt;, &lt;a href="http://pll.cpsc.ucalgary.ca/charity1/www/home.html"&gt;Charity&lt;/a&gt;).

&lt;li&gt;
Some of these choices may not be real options for programing with dependent types. Twelf is designed for programming about programming languages, and, if I remember correctly, doesn't have parametric polymorphism because of something having to do with higher-order abstract syntax. Aldor can't understand most type equalities, making its dependent types somewhat weak, though &lt;a href="http://www.cs.kent.ac.uk/people/staff/sjt/Atypical/"&gt;Atypical and Aldor-- aimed to remedy this five years ago&lt;/a&gt;. Agda and Epigram have New Exciting Versions 2 coming out, so they suffer from &lt;a href="http://en.wikipedia.org/wiki/Osborne_Effect"&gt;the Osborne Effect&lt;/a&gt;.
&lt;/ul&gt;

Is it time yet to do anything about the cornucopia of options? When Haskell began, there were many &lt;em&gt;similar&lt;/em&gt; options; the list above is heterogeneous. Is that because it's too early in to tell what the Right choices will be? Is this problem fundamentally harder than the one that inspired the Haskell precursors?

&lt;p&gt;
I'm not sure, though deciding how to ensure termination seems particularly tricky. Nonetheless, there are other decisions that aren't as directly related to the central dependent type issues, like syntax, functional purity (though this is related to termination), and editing environment. Maybe these issues will divide the ecosystem into a few niches, each dominated by one player. In the meantime, it's tough to choose.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-8473302617671836402?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/8473302617671836402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=8473302617671836402' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8473302617671836402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8473302617671836402'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/12/common-language-for-dependently-typed.html' title='A common language for dependently-typed programming?'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-8255962414155147935</id><published>2007-11-09T18:11:00.000-08:00</published><updated>2007-11-09T21:12:08.593-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Heyting algebra'/><title type='text'>Lectures on the Curry-Howard Isomorphism saves the day</title><content type='html'>&lt;a href="http://www.diku.dk/~rambo/"&gt;Morten Heine B. Sørensen&lt;/a&gt; and &lt;a href="http://www.mimuw.edu.pl/~urzy/"&gt;Pawel Urzyczyn&lt;/a&gt;'s &lt;a href="http://citeseer.ist.psu.edu/519604.html"&gt;&lt;cite&gt;Lectures on the Curry-Howard Isomorphism&lt;/cite&gt;&lt;/a&gt; (&lt;a href="http://folli.loria.fr/cds/1999/library/pdf/curry-howard.pdf"&gt;mirror 1&lt;/a&gt;, &lt;a href="ftp://ftp.mimuw.edu.pl/People/urzy/ch.ps.gz"&gt;mirror 2&lt;/a&gt;, &lt;a href="ftp://ftp.mimuw.edu.pl/People/urzy/errata127.ps.gz"&gt;errata&lt;/a&gt;) provides answers to two questions I asked here before:

&lt;p&gt;

&lt;a href="http://blog.jbapple.com/2007/08/are-there-any-zero-knowledge-proofs.html"&gt;I speculated about a complexity problem and its relation to types&lt;/a&gt;. On page 104 of LotCHI (92, in print), the authors note that, in the simply-typed lambda calculus, a reduction of the type inhabitation problem to the type checking problem would show that P = PSPACE.

&lt;p&gt;
&lt;a href="http://blog.jbapple.com/2007/08/leibniz-equality-decomposition-and.html"&gt;I also wondered if there was a Heyting algebra for higher-order polymorphic typed lambda calculi that we can use to show that some type is uninhabited&lt;/a&gt;. LotCHI section 12.2 gets part of the way there (The authors cover F2, I would need F3, I think.), with the answer that yes, there is such an algebra, but no, it doesn't make things so easy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-8255962414155147935?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/8255962414155147935/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=8255962414155147935' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8255962414155147935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8255962414155147935'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/11/lectures-on-curry-howard-isomorphism.html' title='&lt;cite&gt;Lectures on the Curry-Howard Isomorphism&lt;/cite&gt; saves the day'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-7023054184215987116</id><published>2007-09-04T19:17:00.000-07:00</published><updated>2008-03-23T16:43:16.935-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fuzzy logic'/><category scheme='http://www.blogger.com/atom/ns#' term='constructive logic'/><title type='text'>Fuzzy Logic and Inuitionistic Logic</title><content type='html'>&lt;p&gt;
I recently got rid of a pop science book on &lt;a href="http://en.wikipedia.org/wiki/Fuzzy_logic"&gt;fuzzy logic&lt;/a&gt; that I purchased about eight years ago. When I first read it, it seemed to me to be not all that interesting, since it didn't seem like it created any particularly new ways of thinking about things. After all, calling someone "tall" is just shorthand, and it's not exactly revolutionary to call someone "somewhat tall" or "48% tall", since we can do that already when we talk about any continuous domain.
&lt;p&gt;
I put the book aside and figured that I either didn't get it, I had picked a bad explanation, or it truly was not something I would be interested in.
&lt;p&gt;
It occurs to me now that the idea of indeterminate truth should be very interesting to me, since I'm interested in intuitionistic logic, especially where provability differs from truth. The &lt;a href="http://plato.stanford.edu/"&gt;Stanford Encyclopedia of Philosophy&lt;/a&gt; &lt;a href="http://plato.stanford.edu/entries/logic-fuzzy/"&gt;indicates that the fuzzy logic I was thinking of is the "broad sense" or "fuzzy control", and that there's a whole other sense  of fuzzy logic that is more closely related to my interests.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-7023054184215987116?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/7023054184215987116/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=7023054184215987116' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/7023054184215987116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/7023054184215987116'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/09/fuzzy-logic-and-inuitionistic-logic.html' title='Fuzzy Logic and Inuitionistic Logic'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-6808416011239950610</id><published>2007-09-04T19:16:00.000-07:00</published><updated>2007-09-04T22:19:16.686-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zero-knowledge proof'/><title type='text'>Are there any Zero-Knowledge Proofs?</title><content type='html'>&lt;a href="http://blog.jbapple.com/2007/02/existentials-and-zero-knowledge-proofs.html"&gt;I speculated before about zero-knowledge proofs and existentials&lt;/a&gt;. What I had in mind was encoding knowledge hiding via types. I suspect this result would be more interesting than I had imagined. Here is my understanding:

&lt;p&gt;
Zero-knowledge proofs are interactive proofs, and are therefore in the class &lt;a href="http://en.wikipedia.org/wiki/IP_%28complexity%29"&gt;IP&lt;/a&gt;. This class is the same as &lt;a href="http://en.wikipedia.org/wiki/PSPACE"&gt;PSPACE&lt;/a&gt;, which is not yet known to be distinct from P (though it certainly contains P). So, it's possible that P = IP = PSPACE, and ZK proofs can't hide anything the verifier couldn't calculate herself. In other words, we may one day discover that most of our ZK proof protocols are useless. (This is not the whole story, as there are lots of variations on interactive proving.)

&lt;p&gt;
So, if there were a correspondence between these ZK proofs and existential types, it would either settle the P = PSPACE problem or discover a problem in type theory that is equivalent to it.

&lt;p&gt;
Each of these seems quite unlikely to me. 

&lt;p&gt;
&lt;a href="http://www.infsec.cs.uni-sb.de/~maffei/ResTeach.html"&gt;There is at least one person, however, who is doing research about the relationship between types and cryptography.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-6808416011239950610?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/6808416011239950610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=6808416011239950610' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/6808416011239950610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/6808416011239950610'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/08/are-there-any-zero-knowledge-proofs.html' title='Are there any Zero-Knowledge Proofs?'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-1538703260125065458</id><published>2007-08-28T07:49:00.000-07:00</published><updated>2007-08-28T09:21:35.884-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cardinal numbers'/><title type='text'>Naming Large Integers is Naming Strong Logics</title><content type='html'>Scott Aaronson's &lt;a href="http://www.scottaaronson.com/writings/bignumbers.html"&gt;Who Can Name the Bigger Number?&lt;/a&gt; was &lt;a href="http://programming.reddit.com/info/2jbud/comments"&gt;recently discussed on the programming subreddit&lt;/a&gt;. One of the comments noted the &lt;a href="http://web.mit.edu/arayo/www/bignums.html"&gt;Big Number Duel&lt;/a&gt;, which was inspired by Aaronson's article. The winning entry in the duel was
&lt;blockquote&gt;
The smallest number bigger than any finite number named by an expression in the language of set theory with a googol symbols or less.
&lt;/blockquote&gt;

I think we can do a little bit better without increasing from 10&lt;sup&gt;100&lt;/sup&gt; the number of symbols allowed:

&lt;blockquote&gt;
The smallest number bigger than any finite number named by an expression in the language of set theory &lt;em&gt;plus an axiom stating the existence of a proper class of &lt;a href="http://en.wikipedia.org/wiki/Inaccessible_cardinal"&gt;inaccessible cardinals&lt;/a&gt;&lt;/em&gt; with a googol symbols or less.
&lt;/blockquote&gt;

&lt;p&gt;

Since this theory (&lt;a href="http://en.wikipedia.org/wiki/ZFC"&gt;ZFC&lt;/a&gt;+class of inaccessibles) is stronger than ZFC by itself, I suspect it will define larger integers in the same number of symbols. We could continue along this track by listing &lt;a href="http://en.wikipedia.org/wiki/List_of_large_cardinal_properties"&gt;larger cardinals&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Category:Axioms_of_set_theory"&gt;stronger axioms of set theory&lt;/a&gt;. This game now becomes essentially Bram Cohen's &lt;a href="http://bitconjurer.org/minefield.html"&gt;MineField&lt;/a&gt;, in which we are not naming just numbers, but logics.

&lt;p&gt;

Besides the Big Number Duel, another test of the "name large integers" game was the &lt;a href="http://djm.cc/dmoews.html"&gt;C Bignum Bakeoff&lt;/a&gt;, which asked contestants to wite a C program that returned a large number. Ralph Loader won by to shoehorning a logic called the Calculus of Constructions into his entry, then simply saying something like "the largest integer definable in the Calculus of Constructions using less than a googol symbols".

&lt;p&gt;

The idea of naming finite numbers by extending the strength of not only the working notation but also the working logic is not new; see &lt;a href="http://en.wikipedia.org/wiki/Zero_sharp"&gt;0&lt;sup&gt;#&lt;/sup&gt;&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Zero_dagger"&gt;0&lt;sup&gt;†&lt;/sup&gt;&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-1538703260125065458?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/1538703260125065458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=1538703260125065458' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/1538703260125065458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/1538703260125065458'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/08/naming-large-integers-is-naming-strong.html' title='Naming Large Integers is Naming Strong Logics'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-6687997688298412079</id><published>2007-08-23T06:42:00.000-07:00</published><updated>2008-01-22T20:49:12.145-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='laypeople'/><category scheme='http://www.blogger.com/atom/ns#' term='grammar checking'/><category scheme='http://www.blogger.com/atom/ns#' term='static analysis'/><title type='text'>Static Analysis as Grammar Checking</title><content type='html'>&lt;p&gt;
When I explain what I intend to study to friends who don't program, I say something like the text below. I'm still working out the kinks in the analogy, but this is my starting point:
&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;
When we write, we sometimes make mistakes:
&lt;blockquote&gt;
I am hunry when I wake up.
&lt;/blockquote&gt;
So we invented spelling checkers to catch this simple mistake. We did the same thing for computer languages a long time ago, to catch simple mistakes like spelling errors. And, just as we then invented grammar checkers to catch sentences like:
&lt;blockquote&gt;
I am hungrily when I wake up.
&lt;/blockquote&gt;
that spelling checkers wouldn't catch, we also invented more sophisticated methods to catch more sophisticated mistakes in computer programs.
&lt;/p&gt;
&lt;p&gt;
But grammar rules can sometimes restrict how expressive our sentences are if we wish to speak informally, or to be funny or poetic, or to quote someone famous:
&lt;blockquote&gt;
You've got a friend in Pennsylvania.&lt;br/&gt;
What price justice?&lt;br/&gt;
Hand me a hypodeemic nerdle.
&lt;/blockquote&gt;
For computer programs, we try to characterize useful patterns (like "rhetorical question" or "implicit subject in imperative" in English) and build sets of rules called &lt;em&gt;type systems&lt;/em&gt;. These sets of rules are designed to allow these patterns without allowing incorrect constructions. Type systems require all incorrect constructions to be corrected by the author before a program is run.
&lt;/p&gt;
&lt;p&gt;At the same time, we can build more permissive tools that look for particular patterns that are likely to be errors, like &lt;a href="http://www.uic.edu/com/eye/LearningAboutVision/EyeSite/OpticalIllustions/Paris.shtml"&gt;repeated words&lt;/a&gt; or a lowercase letter following a question mark. Anything flagged by the tool as possibly erroneous can be inspected by the author and corrected if necessary.
&lt;/p&gt;
&lt;p&gt;
The goal of all of this work (called &lt;em&gt;static analysis&lt;/em&gt;) is to catch bugs in software before it is shipped and &lt;a href="http://video.google.com/videosearch?q=ellen+feiss"&gt;bothers users&lt;/a&gt; or  &lt;a href="http://en.wikipedia.org/wiki/Ariane_5_Flight_501"&gt;blows up aerospace equipment&lt;/a&gt;. &lt;!-- or &lt;a href="http://en.wikipedia.org/wiki/Therac-25"&gt;kills cancer patients&lt;/a&gt; --&gt;
&lt;/p&gt;
&lt;p&gt;
My goal is to build new static analysis tools to help prevent rocket explosions and Mac commercials.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-6687997688298412079?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/6687997688298412079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=6687997688298412079' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/6687997688298412079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/6687997688298412079'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/08/static-analysis-as-grammar-checking.html' title='Static Analysis as Grammar Checking'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-8690048312906662507</id><published>2007-08-22T11:12:00.000-07:00</published><updated>2008-03-23T16:29:28.621-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Heyting algebra'/><category scheme='http://www.blogger.com/atom/ns#' term='Leibniz equality'/><title type='text'>Leibniz Equality, Decomposition, and Definability</title><content type='html'>&lt;p&gt;
In any &lt;a href="http://en.wikipedia.org/wiki/Robinson_arithmetic_Q#Metamathematics"&gt;interesting logic&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_theorems"&gt;there are propositions which are true but not provable&lt;/a&gt;. The same goes for &lt;a href="http://plato.stanford.edu/entries/logic-intuitionistic/"&gt;intuitionistic logic&lt;/a&gt;. By the &lt;a href="http://en.wikipedia.org/wiki/Curry-Howard_isomorphism"&gt;Curry-Howard correspondence&lt;/a&gt;, there are types for which neither the types themselves nor their negations are inhabited in the typed lambda calculus. An example of this is &lt;a href="http://en.wikipedia.org/wiki/Peirce's_law"&gt;Peirce's law&lt;/a&gt;: &lt;code&gt;&amp;forall; p, q . ((p -&gt; q) -&gt; p) -&gt; p&lt;/code&gt;. We can &lt;a href="http://en.wikipedia.org/wiki/Heyting_algebra#Heyting_algebras_as_applied_to_intuitionistic_logic"&gt;use Heyting algebra to show that Peirce's law is not provable in intuitionistic logic&lt;/a&gt;. According to John C. Mitchell's &lt;cite&gt;Foundations for Programming Languages&lt;/cite&gt;, problem 4.3.16, we could also show that this is not provable because:

&lt;blockquote&gt;
. . . if there us a closed lambda term M:((a -&gt; b) -&gt; a) -&gt; a then there is a closed normal form (the normal form of M) of this type. Show that this implicational formula is not provable by showing there is no closed normal form term of this type.
&lt;/blockquote&gt;
&lt;/p&gt;
&lt;p&gt;
In &lt;a href="http://homepage.mac.com/pasalic/p2/"&gt;Emir Pasalic&lt;/a&gt;'s &lt;a href="http://homepage.mac.com/pasalic/p2/papers/thesis.pdf"&gt;PhD thesis&lt;/a&gt;, (end of section 4.2.2, page 80 in the PDF, 70 in print), he mentions that it is unknown whether the following type is inhabited:

&lt;pre&gt;
&amp;forall; a, b, c, d . Equal (a,b) (c,d) -&gt; Equal a c
&lt;/pre&gt;
where type equality is defined by Leibniz equality
&lt;pre&gt;
data Equal a b = Equal (&amp;forall; f . f a -&gt; f b)
&lt;/pre&gt;
To avoid dealing with datatypes or pairs, this can be expanded to
&lt;pre&gt;
&amp;forall; a, b, c, d . 
    (&amp;forall; f . f (&amp;forall; r . (a -&gt; b -&gt; r) -&gt; r) -&gt; f (&amp;forall; s . (c -&gt; d -&gt; s) -&gt; s)) 
    -&gt;
    (&amp;forall; g . g a -&gt; g c)
&lt;/pre&gt;

In &lt;a href="http://www.comp.nus.edu.sg/~sulzmann/manuscript/gadtless.ps"&gt;GADTless Programming in Haskell 98&lt;/a&gt; (Section 6, top of page 13) &lt;a href="http://www.comp.nus.edu.sg/~sulzmann/"&gt;Martin Sulzmann&lt;/a&gt; and &lt;a href="http://users.ox.ac.uk/~wolf2335/"&gt;Meng Wang&lt;/a&gt; call this the decomposition law.
&lt;/p&gt;
&lt;p&gt;
Is there some Heyting algebra for higher-order polymorphic typed lambda calculi that we can use to show that this type is uninhabited?
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-8690048312906662507?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/8690048312906662507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=8690048312906662507' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8690048312906662507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8690048312906662507'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/08/leibniz-equality-decomposition-and.html' title='Leibniz Equality, Decomposition, and Definability'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-7625667769896283845</id><published>2007-07-24T20:51:00.000-07:00</published><updated>2008-03-23T16:36:22.361-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ordinals'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>ε0 in an Ord instance</title><content type='html'>In &lt;a href="http://blog.jbapple.com/2007/07/ord-countable-ordinals-and-idea-of.html" &gt;my last post&lt;/a&gt;, I worked rather hard to approach &amp;epsilon;&lt;sub&gt;0&lt;/sub&gt;, but there is a much simpler way to form a type with an &lt;code&gt;Ord&lt;/code&gt; instance that has order type &amp;epsilon;&lt;sub&gt;0&lt;/sub&gt;, according to &lt;a href="http://citeseer.ist.psu.edu/131185.html" &gt;Trees, Ordinals and Termination&lt;/a&gt; (&lt;a href="http://www.math.tau.ac.il/~nachumd/papers/caap-revised.ps.gz" &gt;mirror&lt;/a&gt;)

&lt;pre&gt;
import List

data Tree = Node | Tree [Tree]

instance Ord Tree where
    compare Node Node = EQ
    compare Node (Tree _) = LT
    compare (Tree _) Node = GT
    compare (Tree x) (Tree y) = compare (sort x) (sort y)

instance Eq Tree where
    x == y = compare x y == EQ   
&lt;/pre&gt;

Or, according to &lt;a href="http://www.math.tau.ac.il/~nachumd/papers/ordinals-new.ps.gz" &gt;Ordinal Arithmetic with List Structures&lt;/a&gt; (&lt;a href="http://citeseer.ist.psu.edu/168717.html" &gt;mirror&lt;/a&gt;)

&lt;pre&gt;
data Cons = Nil | Cons Cons Cons

instance Ord Cons where
    compare Nil Nil = EQ
    compare Nil (Cons _ _) = LT
    compare (Cons _ _) Nil = GT
    compare a@(Cons x' y') b@(Cons x y) =
        case compare x' x of
          LT -&gt; compare y' b
          EQ -&gt; compare y' y
          GT -&gt; compare a y

instance Eq Cons where
    x == y = compare x y == EQ
&lt;/pre&gt;

These representations do not help in the general problem of representing all ordinals less than some ordinal &amp;kappa;, but they are much simpler than our previous method.

&lt;p&gt;

For trees with larger order types, see &lt;a href="http://repository.upenn.edu/cis_reports/238/" &gt;What's so special about Kruskal's theorem and the ordinal &amp;Gamma&lt;sub&gt;0&lt;/sub&gt;&lt;/a&gt; (&lt;a href="http://www.cis.upenn.edu/~jean/gallier-old-pubs.html" &gt;mirror&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-7625667769896283845?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/7625667769896283845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=7625667769896283845' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/7625667769896283845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/7625667769896283845'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/07/0-in-ord-instance.html' title='&amp;epsilon;&lt;sub&gt;0&lt;/sub&gt; in an Ord instance'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-4451561834519323384</id><published>2007-07-23T18:30:00.000-07:00</published><updated>2008-03-23T16:37:25.921-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ordinals'/><title type='text'>Ord, Countable Ordinals, and an Idea of sigfpe</title><content type='html'>&lt;p&gt;
This post is literate Haskell.

&lt;p&gt;
In the comments on my last post about ordinals, &lt;a
href="http://www.blogger.com/profile/08096190433222340957"&gt;sigfpe&lt;/a&gt;
&lt;a
href="http://blog.jbapple.com/2007/07/ordinal-notation-and-computer-proof.html#c2460833816539219994"&gt;
suggests&lt;/a&gt; the following type constructors:

&lt;pre&gt;
type One = ()
type Two = Either One One
type N = [One]
type Nplus1 = Either N One
type NplusN = Either N N
type NtimesN = (N,N)
type NpowN = [N]
type NpowNplusN = Either NpowN N
&lt;/pre&gt;

&lt;p&gt;

The idea is that each of these has an &lt;code&gt;Ord&lt;/code&gt; instance
defined. I think he's suggesting that the &lt;code&gt;Ord&lt;/code&gt; instance
for each (ignoring _|_) has an order type that is the same as the
ordinal its name corresponds to. I have some quibbles with his
implementation, but I really like the idea, and so I'll expand on it
below.

&lt;p&gt;
I'll start with my disagreements. My first is with the order for
&lt;code&gt;NpowN&lt;/code&gt;. In NpowN

&lt;pre&gt;
[[(),()]] &gt; [[()],[(),()]] &gt; [[()],[()],[(),()]] &gt; . . .
&lt;/pre&gt;

&lt;p&gt;
or in simpler form

&lt;pre&gt;
[2] &gt; [1,2] &gt; [1,1,2] &gt; . . .
&lt;/pre&gt;

&lt;p&gt;

Since no ordinal has an infinite decreasing sequence, the order type
of &lt;code&gt;[N]&lt;/code&gt; is not that of an ordinal. For now, we'll just
disregard the &lt;code&gt;[]&lt;/code&gt; type constructor.

&lt;p&gt;

My second quibble is with &lt;code&gt;Times&lt;/code&gt;. sigfpe does not make
this explicit, but the inference I drew from his examples was that we
could define &lt;code&gt;Times&lt;/code&gt; as

&lt;pre&gt;
type Times = (,)
&lt;/pre&gt;

&lt;p&gt;

That doesn't quite work, though. &lt;a
href="http://en.wikipedia.org/wiki/Ordinal_arithmetic#Multiplication"&gt;Ordinal
arithmetic&lt;/a&gt; places the least significant part first, but the
&lt;code&gt;Ord&lt;/code&gt; instance for &lt;code&gt;(,)&lt;/code&gt; places the most
significant part first.

&lt;p&gt;

Now that we have these differences out of the way, let's get to the code.

&lt;p&gt;

We'll need these options for type class machinery later.

&lt;pre&gt;

&gt; {-# OPTIONS -fglasgow-exts #-}
&gt; {-# OPTIONS -fallow-incoherent-instances #-}

&lt;/pre&gt;

&lt;p&gt;

Ala sigfpe:

&lt;pre&gt;

&gt; type One = ()
&gt; type Plus = Either
&gt; type Times = Flip Both
&gt;
&gt; data Both a b = Both a b
&gt; newtype Flip f a b = Flip (f b a)

&lt;/pre&gt;

&lt;p&gt;

To define &lt;code&gt;Times&lt;/code&gt;, we use a pair datatype with the standard
Haskell ordering (see &lt;code&gt;instance Ordinal2 Both&lt;/code&gt; below), but
apply the newtype &lt;code&gt;Flip&lt;/code&gt;, which warrants its own
definition, as it will be useful elsewhere.

&lt;p&gt;

So far, we can only define finite ordinals. In order to represent
larger ordinals, we want to be able to represent an unlimited number
of applications of a type constructor to a type.

&lt;pre&gt;

&gt; data ApplyN f x = More (ApplyN f (f x))
&gt;                 | Stop x

&lt;/pre&gt;

&lt;p&gt;

&lt;code&gt;ApplyN&lt;/code&gt; does this -- after n applications of
&lt;code&gt;More&lt;/code&gt;, the type &lt;code&gt;x&lt;/code&gt; is wrapped n times in the
type constructor &lt;code&gt;f&lt;/code&gt;. Essentially, &lt;code&gt;ApplyN f x&lt;/code&gt;
is f&lt;sup&gt;&amp;omega;&lt;/sup&gt;(x).

&lt;p&gt;

Our first example of this will be adding one &amp;omega; times.

&lt;pre&gt;

&gt; type N = ApplyN (Flip Plus One) One

&lt;/pre&gt;

&lt;p&gt;

&lt;!--
I'll explain the reason for the &lt;code&gt;Flip&lt;/code&gt; later. For now, this
should look like (&amp;lambda; x . x + 1)&lt;sup&gt;&amp;omega;&lt;/sup&gt; (1).
--&gt;

This should look like (&amp;lambda; x . x + 1)&lt;sup&gt;&amp;omega;&lt;/sup&gt; (1).

&lt;p&gt;

If &lt;code&gt;ApplyN&lt;/code&gt; works as advertized, &lt;code&gt;N&lt;/code&gt; should have
order type &amp;omega; under a naive definition of
&lt;code&gt;Ord&lt;/code&gt;. Unfortunately, it does not. First of all, we can't
automatically derive &lt;code&gt;Ord&lt;/code&gt; for the type
&lt;code&gt;ApplyN&lt;/code&gt;, since it uses a type constructor, &lt;code&gt;f&lt;/code&gt;,
to build a new parameter. We will need

&lt;pre&gt;

&gt; class Ordinal1 f where
&gt;     comp1 :: Ordinal a =&gt; f a -&gt; f a -&gt; Ordering

&lt;/pre&gt;

&lt;p&gt;

to describe the contract &lt;code&gt;f&lt;/code&gt; must meet to make &lt;code&gt;ApplyN
f x&lt;/code&gt; ordered. Note that we use the class &lt;code&gt;Ordinal&lt;/code&gt;
here, which is used only to avoid messing the with &lt;code&gt;Eq&lt;/code&gt;
requirement on instances for &lt;code&gt;Ord&lt;/code&gt;.

&lt;pre&gt;

&gt; class Ordinal t where
&gt;     comp :: t -&gt; t -&gt; Ordering

&lt;/pre&gt;

&lt;p&gt;

The second problem with the naive instance of &lt;code&gt;Ordinal&lt;/code&gt; on
&lt;code&gt;ApplyN&lt;/code&gt; is that each application of &lt;code&gt;More&lt;/code&gt;
leads to a new type closer to the type we're really talking
about. What I mean by this is that, for the case of &lt;code&gt;N&lt;/code&gt;, we
really want to talk about 

&lt;pre&gt;
Flip Plus One (Flip Plus One (Flip Plus One . . . .
&lt;/pre&gt;

&lt;p&gt;

Which we can't directly say in Haskell.

&lt;p&gt;

We want to be talking about the type that is the limit. Since we can't
do that, to compare two values, we'll compare them at the maximum of
their levels. For instance, if we want to compare the values &lt;code&gt;Stop
()&lt;/code&gt; and &lt;code&gt; More $ More $ Stop $ Flip $ Left $ Flip $ Left
()&lt;/code&gt;, both of which are of type &lt;code&gt;N&lt;/code&gt;, we'll inject the
value &lt;code&gt;()&lt;/code&gt; into the higher level. To do this, we also need
&lt;code&gt;f&lt;/code&gt; to be have the property that we can inject into it a
value of its type parameter.

&lt;pre&gt;

&gt; class Container f where
&gt;     inject :: x -&gt; f x

&lt;/pre&gt;

&lt;p&gt;

To bring this back to the ordinals, we'll be representing
&amp;omega;&lt;sup&gt;&amp;omega;&lt;/sup&gt; as either and ordinal less than &amp;omega;, or an
ordinal less than &amp;omega;&lt;sup&gt;2&lt;/sup&gt;, or an ordinal less than
&amp;omega;&lt;sup&gt;3&lt;/sup&gt; or &amp;hellip;, and to compare two ordinals, we get a
representation of each in a common level, then compare them using the
comparison for ordinals less than the limiting ordinal of that level.

&lt;pre&gt;

&gt; instance (Container f, Ordinal1 f) =&gt; Ordinal1 (ApplyN f) where
&gt;     comp1 (Stop u) (Stop v) = comp u v
&gt;     comp1 (Stop u) (More v) = comp (Stop (inject u)) v
&gt;     comp1 (More u) (Stop v) = comp u (Stop (inject v))
&gt;     comp1 (More u) (More v) = comp1 u v

&lt;/pre&gt;

&lt;p&gt;

We've defined the ordering on &lt;code&gt;ApplyN f&lt;/code&gt; so that 

&lt;pre&gt;
comp (Stop x) (More (Stop (inject x))) == EQ
&lt;/pre&gt;

&lt;p&gt;

which is what the paragraph above says, but more concise. We've
defined an equivalence relation on values of the type &lt;code&gt;ApplyN f
t&lt;/code&gt; such that &lt;code&gt;x == inject x&lt;/code&gt;, so we're off to a good
start.

&lt;p&gt;

We'll also want &lt;code&gt;inject&lt;/code&gt; to be monotone, that is

&lt;pre&gt;
 x &lt; y ==&gt; inject x &lt; inject y
&lt;/pre&gt;

&lt;p&gt;

and for &lt;code&gt;inject&lt;/code&gt; to send the order type of the domain not
just to &lt;em&gt;some&lt;/em&gt; order in the codomain, but to the initial order
in the codomain. So, it's easy to write

&lt;pre&gt;

&gt; injectPlusL :: a -&gt; Plus a b
&gt; injectPlusL x = Left x

&lt;/pre&gt;

&lt;p&gt;

or

&lt;pre&gt;

&gt; instance Container (Flip Plus b) where
&gt;     inject v = Flip (Left v)

&lt;/pre&gt;

&lt;p&gt;

Injecting a into a*b is trickier, since we need the second part of the
pair to be the minimal possible value in order for the injection range
to be the initial part of the order. For this we define

&lt;pre&gt;

&gt; class Least x where
&gt;     least :: x
&gt; instance Least One where
&gt;     least = ()
&gt; instance Least a =&gt; Least (Plus a b) where
&gt;     least = Left least
&gt; instance (Least a, Least b) =&gt; Least (Times a b) where
&gt;     least = Flip (Both least least)
&gt; instance Least b =&gt; Least (Flip Plus a b) where
&gt;     least = Flip (Left least)
&gt; instance (Least a, Least b) =&gt; Least (Flip Times a b) where
&gt;     least = Flip (Flip (Both least least))
&gt; instance Least x =&gt; Least (ApplyN f x) where
&gt;     least = Stop least

&lt;/pre&gt;

&lt;p&gt;

And we can now write the injection from a to a*b:

&lt;pre&gt;

&gt; instance (Least a) =&gt; Container (Flip Times a) where
&gt;     inject v = Flip (Flip (Both least v))

&lt;/pre&gt;

&lt;p&gt;

We also have the trivial

&lt;pre&gt;

&gt; instance Container (ApplyN f) where
&gt;     inject x = Stop x

&lt;/pre&gt;

&lt;p&gt;

Let's write the base instances for Ordinal in as general a way as possible:

&lt;pre&gt;

&gt; class Ordinal2 f where
&gt;     comp2 :: (Ordinal a, Ordinal b) =&gt; f a b -&gt; f a b -&gt; Ordering
&gt; instance Ordinal2 Plus where
&gt;     comp2 (Left _) (Right _) = LT
&gt;     comp2 (Right _) (Left _) = GT
&gt;     comp2 (Left x) (Left y) = comp x y
&gt;     comp2 (Right x) (Right y) = comp x y
&gt; instance Ordinal2 Both where
&gt;     comp2 (Both p q) (Both x y) = 
&gt;         case comp p x of
&gt;           LT -&gt; LT
&gt;           GT -&gt; GT
&gt;           EQ -&gt; comp q y
&gt; instance Ordinal2 f =&gt; Ordinal2 (Flip f) where
&gt;     comp2 (Flip x) (Flip y) = comp2 x y
&gt;
&gt; instance Ordinal () where
&gt;     comp _ _ = EQ

&lt;/pre&gt;

&lt;p&gt;

And the conversion instances between the n-ary Ordinal instances:

&lt;pre&gt;

&gt; instance (Ordinal1 f, Ordinal a) =&gt; Ordinal (f a) where
&gt;     comp = comp1
&gt; instance (Ordinal2 f, Ordinal a, Ordinal b) =&gt; Ordinal (f a b) where
&gt;     comp = comp2
&gt; instance (Ordinal2 f, Ordinal a) =&gt; Ordinal1 (f a) where
&gt;     comp1 = comp2

&lt;/pre&gt;

&lt;p&gt;

Now let's do some examples. First we check that &lt;code&gt;Ordinal&lt;/code&gt; is
defined for &lt;code&gt;N&lt;/code&gt;:

&lt;pre&gt;

&gt; n_ok = comp (undefined :: N) (undefined :: N)

&lt;/pre&gt;

&lt;p&gt;

&amp;omega;&lt;sup&gt;&amp;omega;&lt;/sup&gt;:

&lt;pre&gt;

&gt; type NpowN = ApplyN (Flip Times N) One
&gt; npowN_ok = comp (undefined :: NpowN) (undefined :: NpowN)

&lt;/pre&gt;

&lt;p&gt;

We can now plug in &lt;code&gt;NpowN&lt;/code&gt; into its own definition to get
&amp;omega;&lt;sup&gt;&amp;omega;&lt;/sup&gt; * &amp;omega; = &amp;omega;&lt;sup&gt;&amp;omega; + 1&lt;/sup&gt;

&lt;pre&gt;

&gt; type NpowNplusOne = ApplyN (Flip Times N) NpowN
&gt; nPowNplusOne_ok = comp (undefined :: NpowNplusOne) (undefined :: NpowNplusOne)

&lt;/pre&gt;

or &amp;omega;&lt;sup&gt;&amp;omega; * &amp;omega;&lt;/sup&gt; =
&amp;omega;&lt;sup&gt;&amp;omega;&lt;sup&gt;2&lt;/sup&gt;&lt;/sup&gt;:

&lt;pre&gt;

&gt; type NpowNpow2 = ApplyN (Flip Times NpowN) One
&gt; npowNpow2_ok = comp (undefined :: NpowNpow2) (undefined :: NpowNpow2)

&lt;/pre&gt;

&lt;p&gt;

The second method looks more powerful, but continuing it keeps us
below &amp;omega;&lt;sup&gt;&amp;omega;&lt;sup&gt;&amp;omega&lt;/sup&gt;&lt;/sup&gt;, so let's use the
first method of substituting back in to see if we can get further.

&lt;p&gt;

&amp;omega;&lt;sup&gt;&amp;omega; + 2&lt;/sup&gt;:

&lt;pre&gt;

&gt; type NpowNplus2 = ApplyN (Flip Times N) NpowNplusOne
&gt; nPowNplus2_ok = comp (undefined :: NpowNplus2) (undefined :: NpowNplus2)

&lt;/pre&gt;

&lt;p&gt;

We can now plug &lt;code&gt;ApplyN&lt;/code&gt; back into itself, and extend this
to &amp;omega;&lt;sup&gt;&amp;omega; + &amp;omega&lt;/sup&gt; = &amp;omega;&lt;sup&gt;&amp;omega; * 2&lt;/sup&gt;:

&lt;pre&gt;
        
&gt; type NpowNtimes2 = ApplyN (ApplyN (Flip Times N)) One
&gt; npowNtimes2_ok = comp (undefined :: NpowNtimes2) (undefined :: NpowNtimes2)

&lt;/pre&gt;

&lt;p&gt;

Similarly, &amp;omega;&lt;sup&gt;&amp;omega; * 3&lt;/sup&gt;:

&lt;pre&gt;
        
&gt; type NpowNtimes3 = ApplyN (ApplyN (Flip Times N)) NpowNtimes2
&gt; npowNtimes3_ok = comp (undefined :: NpowNtimes3) (undefined :: NpowNtimes3)

&lt;/pre&gt;

&lt;p&gt;

&amp;omega;&lt;sup&gt;&amp;omega; * &amp;omega;&lt;/sup&gt; =
&amp;omega;&lt;sup&gt;&amp;omega;&lt;sup&gt;2&lt;/sup&gt;&lt;/sup&gt;, which we apready saw before,
can also be written as

&lt;pre&gt;
        
&gt; type NpowNpow2' = ApplyN (ApplyN (ApplyN (Flip Times N))) One
&gt; npowNpow2'_ok = comp (undefined :: NpowNpow2') (undefined :: NpowNpow2')

&lt;/pre&gt;

&lt;p&gt;

&amp;omega;&lt;sup&gt;&amp;omega;&lt;sup&gt;2&lt;/sup&gt; * &amp;omega;&lt;/sup&gt; = &amp;omega;&lt;sup&gt;&amp;omega;&lt;sup&gt;3&lt;/sup&gt;&lt;/sup&gt; = 

&lt;pre&gt;
        
&gt; type NpowNpow3 = ApplyN (ApplyN (ApplyN (Flip Times N))) NpowNpow2
&gt; npowNpow3_ok = comp (undefined :: NpowNpow3) (undefined :: NpowNpow3)

&lt;/pre&gt;

&lt;p&gt;

&amp;omega;&lt;sup&gt;&amp;omega;&lt;sup&gt;&amp;omega;&lt;/sup&gt;&lt;/sup&gt;:

&lt;pre&gt;
        
&gt; type NpowNpowN = ApplyN (ApplyN (ApplyN (ApplyN (Flip Times N)))) One
&gt; npowNpowN_ok = comp (undefined :: NpowNpowN) (undefined :: NpowNpowN)

&lt;/pre&gt;

&lt;p&gt;

&amp;omega;&lt;sup&gt;&amp;omega;&lt;sup&gt;&amp;omega; + 1&lt;/sup&gt;&lt;/sup&gt;:

&lt;pre&gt;
        
&gt; type NpowNpowNplusOne = ApplyN (ApplyN (ApplyN (ApplyN (Flip Times N)))) NpowNpowN
&gt; npowNpowNplusOne_ok = comp (undefined :: NpowNpowNplusOne) (undefined :: NpowNpowNplusOne)

&lt;/pre&gt;

&lt;p&gt;

We can continue this process up to, but not including,
&amp;epsilon;&lt;sub&gt;0&lt;/sub&gt;. We might be able to go further than this, but
I'll save that for later.

&lt;p&gt;

Thanks to sigfpe for the idea!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-4451561834519323384?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/4451561834519323384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=4451561834519323384' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/4451561834519323384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/4451561834519323384'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/07/ord-countable-ordinals-and-idea-of.html' title='Ord, Countable Ordinals, and an Idea of sigfpe'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-7868504782448649445</id><published>2007-07-20T20:19:00.000-07:00</published><updated>2008-03-23T16:35:45.763-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ordinals'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>Ordinal Notation and Computer Proof</title><content type='html'>&lt;p&gt;
&lt;a href="http://blog.jbapple.com/2007/06/ordinals-part-2.html" &gt;Last ordinal post here&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://coq.inria.fr/contribs/Cantor.html" &gt;There is an implementation in Coq of the countable ordinals up to &amp;Gamma;&lt;sub&gt;0&lt;/sub&gt;&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-7868504782448649445?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/7868504782448649445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=7868504782448649445' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/7868504782448649445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/7868504782448649445'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/07/ordinal-notation-and-computer-proof.html' title='Ordinal Notation and Computer Proof'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-3751056714695966153</id><published>2007-07-20T14:55:00.000-07:00</published><updated>2008-03-23T16:42:18.939-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='referential transparency'/><category scheme='http://www.blogger.com/atom/ns#' term='Coq'/><title type='text'>More Proof of Referential Transparency</title><content type='html'>&lt;p&gt;
&lt;a href="http://blog.jbapple.com/2007/06/proof-of-referential-transparency.html" &gt;Previously, I talked about proving referential transparency&lt;/a&gt;. The authors of &lt;a href="http://www.lri.fr/~filliatr/puf/index.en.html" &gt;A Persistent Union-Find Data Structure&lt;/a&gt; (&lt;a href="http://www.lri.fr/~filliatr/ftp/publis/puf-wml07.ps" &gt;other version&lt;/a&gt;) use &lt;a href="http://coq.inria.fr/" &gt;Coq&lt;/a&gt; to prove imperative functions referentially transparent, and they point out the work of &lt;a href="http://home.pipeline.com/~hbaker1/" &gt;Harold Baker&lt;/a&gt;, who designed &lt;a href="http://citeseer.ist.psu.edu/245043.html" &gt;fast persistent arrays&lt;/a&gt; (&lt;a href="http://citeseer.ist.psu.edu/250000.html" &gt;and here&lt;/a&gt;), which they also prove to be referentially transparent. &lt;a href="http://www.haskell.org/ghc/docs/6.8.2/html/libraries/array/Data-Array-Diff.html"&gt;These arrays are even available in Haskell&lt;/a&gt;, though wrapped in the IO monad.
&lt;/p&gt;
&lt;p&gt;
The authors of the union-find paper say that their structure is not "purely applicative". I don't actually know what that means, but I suppose it means it's not strictly functional, since it requires in-place modification.
&lt;/p&gt;
&lt;p&gt;
In any case, there are now at least four cases for being able to prove referential transparency so we can use it without wrapping everything in the IO monad:
&lt;ul&gt;
&lt;li&gt; Memoization - &lt;a href="http://research.microsoft.com/Users/simonpj/Papers/weak.htm" &gt;For memoization in (not just for) Haskell, see this paper by the Simons and Conal Elliott.&lt;/a&gt; (&lt;a href="http://citeseer.ist.psu.edu/peytonjones99stretching.html" &gt;mirror 1&lt;/a&gt;, &lt;a href="http://conal.net/papers/weak.ps" &gt;mirror 2&lt;/a&gt;)
&lt;li&gt; Diff Arrays
&lt;li&gt; Splay Trees
&lt;li&gt; Union-Find
&lt;/ul&gt;
Any other ideas?
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-3751056714695966153?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/3751056714695966153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=3751056714695966153' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/3751056714695966153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/3751056714695966153'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/07/more-proof-of-referential-transparency.html' title='More Proof of Referential Transparency'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-2078216538647453280</id><published>2007-06-30T09:02:00.000-07:00</published><updated>2008-03-23T16:32:15.639-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='V=L'/><category scheme='http://www.blogger.com/atom/ns#' term='countability'/><category scheme='http://www.blogger.com/atom/ns#' term='constructive logic'/><category scheme='http://www.blogger.com/atom/ns#' term='ordinals'/><title type='text'>Constructability, Uncountability, and ω-Haskell</title><content type='html'>&lt;p&gt;
&lt;a href="http://japple.blogspot.com/2007/06/ordinals-part-2.html"&gt;My last post about the uncountable ordinals&lt;/a&gt; &lt;a href="http://programming.reddit.com/info/22e5n/comments"&gt;ended up on the programming subreddit&lt;/a&gt;, where &lt;a href="http://programming.reddit.com/user/augustss"&gt;someone who I think is Lennart Augustsson&lt;/a&gt; &lt;a href="http://programming.reddit.com/info/22e5n/comments/c22f2w"&gt;said&lt;/a&gt;:
&lt;blockquote&gt;
Wow, I didn't realize you could do this. Now I have to wrap my brain around in what sense you can represent uncountable ordinals in Haskell since there are only a countable number of Haskell programs. It must be something like constructive reals...
&lt;/blockquote&gt;
&lt;/p&gt;
&lt;p&gt;
I think he's exactly right, and I think it has something to do with &lt;a href="http://en.wikipedia.org/wiki/V=L"&gt;V=L&lt;/a&gt;, models, and &lt;a href="http://japple.blogspot.com/2007/02/definability-and-continuity.html"&gt;how many functions are definable in Haskell&lt;/a&gt;. I'm going out of my comfort zone on this, so please correct me if I make any incorrect or nonsensical statements. I'll use as my example the powerset of the natural numbers, which is certainly uncountable, and already definable in Haskell with
&lt;pre&gt;
data Nat = Z | S Nat
type Powerset t = t -&gt; Bool
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
From the viewpoint of ZFC, there are an uncountable number of ZFC functions from the natural numbers to the booleans. From the viewpoint of Haskell, there are an uncountable number of Haskell functions from the natural numbers to the booleans. But, from the world of ZFC, the number of Haskell functions from the natural numbers to the booleans is countable: we can simply order them by their definitions lexicographically. Since every function definable in Haskell has a finite definition and the cardinality of a countable union of finite sets is countable, the function definitions of type &lt;code&gt;Nat -&gt; Bool&lt;/code&gt; are countable.
&lt;/p&gt; 
&lt;div align="center"&gt;
|{f : f &lt;- (&lt;b&gt;N&lt;/b&gt; -&gt; 2)&lt;sub&gt;ZFC&lt;/sub&gt;}| &gt;&lt;sub&gt;ZFC&lt;/sub&gt; |&lt;b&gt;N&lt;/b&gt;|&lt;br&gt;
|{f : f &lt;- (&lt;b&gt;N&lt;/b&gt; -&gt; 2)&lt;sub&gt;Haskell&lt;/sub&gt;}| &gt;&lt;sub&gt;Haskell&lt;/sub&gt; |&lt;b&gt;N&lt;/b&gt;|&lt;br&gt;
|{f : f &lt;- (&lt;b&gt;N&lt;/b&gt; -&gt; 2)&lt;sub&gt;Haskell&lt;/sub&gt;}| =&lt;sub&gt;ZFC&lt;/sub&gt; &amp;Sigma;&lt;sub&gt;n &lt;- &lt;b&gt;N&lt;/b&gt;&lt;/sub&gt; |all n-bit functions from &lt;b&gt;N&lt;/b&gt; -&gt; Bool| = |&lt;b&gt;N&lt;/b&gt;|&lt;br&gt;
&lt;/div&gt;
&lt;p&gt;
From the viewpoint of Haskell, though, this can't be proven; functions are opaque, so we have no way to order or count them. This might not be true if we use some of the unsafe features of Haskell that would allow us to look at the actual assembly corresponding to a function.
&lt;/p&gt;
&lt;p&gt;
We could, I suppose, imagine a programming language which was not limited to finite-length function definitions. &amp;omega;-Haskell would not only have types with seemingly uncountable numbers of inhabitants, but each inhabitant would also be definable. Yuk!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-2078216538647453280?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/2078216538647453280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=2078216538647453280' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2078216538647453280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2078216538647453280'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/06/constructability-uncountability-and.html' title='Constructability, Uncountability, and &amp;omega;-Haskell'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-5839509165539293360</id><published>2007-06-30T08:47:00.000-07:00</published><updated>2008-03-23T16:39:48.421-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='effect inference'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Region, Effect and Closure Inference, Part 2</title><content type='html'>&lt;p&gt;
&lt;a href="http://japple.blogspot.com/2007/06/proof-of-referential-transparency.html"&gt;Part 1&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.blogger.com/profile/05322254915965832369"&gt;Michael Stone&lt;/a&gt; was correct in his comments to part 1. Ben Lippmeier elaborated to me in an email:
&lt;blockquote&gt;
In those slides,
&lt;br&gt;
(%) is the kind of regions.&lt;br&gt;
(!) is the kind of effects.&lt;br&gt;
($) is the kind of closures.&lt;br&gt;
&lt;br&gt;
The symbol represents the kind, as well as the name space of the R/E/C variables.
&lt;br&gt;
&amp;hellip;
&lt;br&gt;
I don't have a paper for this stuff at the moment, it's still under development - but the type system is based on some other work that has been around for a while:
&lt;br&gt;
The Type and Effect Discipline&lt;br&gt;
Jean-Pierre Talpin, Pierre Jouvelot&lt;br&gt;
&lt;br&gt;
Polymorphic Type, Region and Effect Inference&lt;br&gt;
Jean-Pierre Talpin, Pierre Jouvelot&lt;br&gt;
&lt;br&gt;
Polymorphic type inference and assignment&lt;br&gt;
(For the closure typing)&lt;br&gt;
Xavier Leroy&lt;br&gt;
&lt;br&gt;
The type system is a merge of the ones described in the above two papers, but with some extra stuff added on to make it practical to use in a real compiler.
&lt;/blockquote&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-5839509165539293360?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/5839509165539293360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=5839509165539293360' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/5839509165539293360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/5839509165539293360'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/06/region-effect-and-closure-inference.html' title='Region, Effect and Closure Inference, Part 2'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-2544858816282384802</id><published>2007-06-29T17:56:00.000-07:00</published><updated>2008-03-23T16:52:42.680-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='countability'/><category scheme='http://www.blogger.com/atom/ns#' term='ordinals'/><title type='text'>Ordinals, part 2</title><content type='html'>&lt;p&gt;
&lt;a href="http://japple.blogspot.com/2007/02/countable-ordinals-in-haskell.html"&gt;Part 1&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://homepages.inf.ed.ac.uk/v1phanc1/"&gt;Peter G. Hancock&lt;/a&gt; &lt;a href="http://sneezy.cs.nott.ac.uk/fplunch/weblog/?p=66"&gt;reminded us of the obvious way to define uncountable ordinals&lt;/a&gt;. A rough translation into a single data type, rather than a family:
&lt;pre&gt;
data Ordinal n = Zero (Nat n)
               | Succ (Ordinal n)
               | forall t . Limit (Less t n) (Ordinal t -&gt; Ordinal n)
&lt;/pre&gt;
The parameter &lt;code&gt;n&lt;/code&gt; is the "class" of the ordinal. We need the helper definitions:
&lt;pre&gt;
data Nat n where
    Z :: Nat Z
    S :: Nat n -&gt; Nat (S n)
data Z
data S n

data Less a b where
    LessZ :: Nat b -&gt; Less Z (S b)
    LessS :: Less a b -&gt; Less (S a) (S b)

embed :: Ordinal n -&gt; Ordinal (S n)
embed (Zero x) = Zero (S x)
embed (Succ x) = Succ (embed x)
embed (Limit e f) = Limit (onemore e) (embed . f)
    where
      onemore :: Less a b -&gt; Less a (S b)
      onemore (LessZ x) = LessZ (S x)
      onemore (LessS p) = LessS (onemore p)

&lt;/pre&gt;
Then we can define the first uncountable ordinal as
&lt;pre&gt;
omega_1 = Limit (LessS (LessZ Z)) embed
&lt;/pre&gt;
and the sequence of &amp;omega;s up to &amp;omega;&lt;sub&gt;&amp;omega;&lt;/sub&gt; as
&lt;pre&gt;
omega_n :: Nat n -&gt; Ordinal n
omega_n Z = Zero Z
omega_n (S n) = Limit (plusone n) embed
    where
      plusone :: Nat n -&gt; Less n (S n)
      plusone Z = LessZ Z
      plusone (S n) = LessS (plusone n)
&lt;/pre&gt;
&lt;p&gt;
Hancock has &lt;a href="http://homepages.inf.ed.ac.uk/v1phanc1/chat.html"&gt;many other interesting ways to represent ordinals&lt;/a&gt;, including &lt;a href="http://homepages.inf.ed.ac.uk/v1phanc1/conway.html"&gt;as surreal numbers&lt;/a&gt; (&lt;a href="http://homepages.inf.ed.ac.uk/v1phanc1/Conway.lhs"&gt;with code&lt;/a&gt;), in which we can provide a more precise answer the the question I was originally responding to, &lt;a href="http://www.randomhacks.net/articles/2007/02/02/divide-infinity-by-2"&gt;What happens when you divide infinite by two?&lt;/a&gt; In the case of surreal numbers, you get, simply, &amp;omega;/2, just as you do with the &lt;a href="http://en.wikipedia.org/wiki/Hyperreal_number"&gt;hyperreals&lt;/a&gt;. Hancock also provides a datatype for the ordinals up to &amp;Gamma;&lt;sub&gt;0&lt;/sub&gt; without resorting to embedded functions, which means we can do things like &lt;a href="http://en.wikipedia.org/wiki/Large_countable_ordinals#Predicative_definitions_and_the_Veblen_hierarchy"&gt;computably compare them&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-2544858816282384802?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/2544858816282384802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=2544858816282384802' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2544858816282384802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2544858816282384802'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/06/ordinals-part-2.html' title='Ordinals, part 2'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-4238148025277585507</id><published>2007-06-23T20:58:00.000-07:00</published><updated>2008-03-23T16:39:17.652-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quotient types'/><category scheme='http://www.blogger.com/atom/ns#' term='referential transparency'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Compiler Proof of Referential Transparency</title><content type='html'>&lt;p&gt;
Programs in languages with mutation can make optimizations that Haskell programs can't, at least not without compiler magic, unsafePerformIO, or wrapping return types in the IO monad. Simple examples that spring to mind are memoization and &lt;a href="http://en.wikipedia.org/wiki/Splay_tree"&gt;splay trees&lt;/a&gt;. Here, operations that should have no semantic effects (calling a &lt;code&gt;fib&lt;/code&gt; function or doing a &lt;code&gt;find&lt;/code&gt; on a splay map) do have actual effects. It would be nice if Haskell programmers could write these optimizations and prove them safe with the type system, then use these functions as if they were referentially transparent.
&lt;/p&gt;
&lt;p&gt;
My idea for this a few months ago was to use quotient types, since quotient types equate two actually different things that are functionally the same under some view.  A Fibonacci function with a memoization table up to 100 looks the same to a caller as one with no memoized values at all, so they are equal under some quotient.
&lt;/p&gt;
&lt;p&gt;
Other things came up, and I put off this idea for a while, and I have now seen a really cool way for Haskell programmers to deal with local effects. &lt;a href="http://cs.anu.edu.au/people/Ben.Lippmeier/"&gt;Ben Lippmeier&lt;/a&gt;'s &lt;a href="http://www.comp.mq.edu.au/~asloane/pmwiki.php/SAPLING/SAPLING071?action=download&amp;upname=lippmeier-slides071.pdf"&gt;talk&lt;/a&gt; at the &lt;a href="http://www.comp.mq.edu.au/~asloane/pmwiki.php/SAPLING/SAPLING071"&gt;SAPLING June 2007 meeting&lt;/a&gt; (&lt;a href="http://www.comp.mq.edu.au/~asloane/pmwiki.php/SAPLING/SAPLING071?action=download&amp;upname=lippmeier071.txt"&gt;talk summary&lt;/a&gt;) explains region and effect inference for Haskell-like languages without sacrificing referential transparency or having to use the IO monad. This insight wouldn't solve the splay tree issue, because reading a splay tree &lt;em&gt;does&lt;/em&gt; modify data that is not local to the reading function, though that modification should be opaque to clients.
&lt;/p&gt;
&lt;p&gt;
I can't wait to see the full paper(s) and the implementation. Until I can, I'll have to settle for &lt;a href="http://www.comp.mq.edu.au/~asloane/pmwiki.php/SAPLING/SAPLING061?action=download&amp;upname=lippmeier061.pdf"&gt;the slides from an earlier talk with more motivation.&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-4238148025277585507?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/4238148025277585507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=4238148025277585507' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/4238148025277585507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/4238148025277585507'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/06/proof-of-referential-transparency.html' title='Compiler Proof of Referential Transparency'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-2752919249456839916</id><published>2007-03-18T18:00:00.000-07:00</published><updated>2008-03-23T16:43:45.912-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zero-knowledge proof'/><category scheme='http://www.blogger.com/atom/ns#' term='constructive logic'/><title type='text'>Existentials and Zero-Knowledge Proofs</title><content type='html'>&lt;p&gt;
When I use "&amp;exist; x . P(x)" in typed programming (using intuitionistic logic), I must have in hand an x and a proof of P(x). This is not the case in the classical logic, in which I might have a proof of &amp;exist; x . P(x) without knowing any details of x at all.
&lt;/p&gt;
&lt;p&gt;
This idea that I know such an x exists though I have no knowledge of it reminds me of &lt;a href="http://en.wikipedia.org/wiki/Zero-knowledge_proof"&gt;zero-knowledge proofs&lt;/a&gt;. Of course, the zero-knowledge proofs referenced in the Wikipedia article aren't so much proofs as they are assurances with high probability. I looked around for zero-knowledge proofs that were more proof-like, but I didn't find much. I wonder if there is any deeper connection between classical existentials and zero-knowledge proofs?
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-2752919249456839916?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/2752919249456839916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=2752919249456839916' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2752919249456839916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2752919249456839916'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/02/existentials-and-zero-knowledge-proofs.html' title='Existentials and Zero-Knowledge Proofs'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-4220869469690788347</id><published>2007-02-18T18:56:00.000-08:00</published><updated>2008-03-23T16:46:43.246-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Simulating Dependent Types with Guarded Algebraic Datatypes'/><category scheme='http://www.blogger.com/atom/ns#' term='GADTs'/><category scheme='http://www.blogger.com/atom/ns#' term='dependent types'/><category scheme='http://www.blogger.com/atom/ns#' term='ML'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Conor's Rule?</title><content type='html'>&lt;p&gt;
&lt;a href="http://www.dcs.st-and.ac.uk/~eb/"&gt;Edwin Brady&lt;/a&gt; writes in &lt;a href="http://edwinb.wordpress.com/2007/02/19/how-to-write-programs-in-two-easy-steps/trackback/"&gt;"How to write programs in two easy steps"&lt;/a&gt;, that

&lt;blockquote&gt;
I think it's also an area where dependently typed languages like &lt;a href="http://www.e-pig.org"&gt;Epigram&lt;/a&gt; will shine, because it will one day be possible to write &lt;a href="http://www.cs.st-andrews.ac.uk/~eb/writings/verified_staged.pdf"&gt; &lt;em&gt;verified&lt;/em&gt; interpreters&lt;/a&gt; for domain specific languages &amp;hellip;
&lt;/blockquote&gt;

I immediately thought "I can &lt;a href="http://www.cs.virginia.edu/~jba5b/singleton"&gt;write dependently typed programs &lt;em&gt;right now&lt;/em&gt; with GADTs&lt;/a&gt;, and I can do so in &lt;a href="http://www.haskell.org/ghc/dist/current/docs/users_guide/data-type-extensions.html#gadt"&gt;GHC Haskell&lt;/a&gt;, &lt;a href="http://www.google.com/search?q=site%3Awww.scala-lang.org+gadts"&gt;Scala&lt;/a&gt;, or the &lt;a href="http://research.microsoft.com/~akenn/generics/index.html"&gt;upcoming C#&lt;/a&gt;". This is, of course, only &lt;em&gt;mostly&lt;/em&gt; true, since none of these does termination checking, and the syntax is awkward.
&lt;/p&gt;





&lt;p&gt;
The same blog post later references &lt;a href="http://en.wikipedia.org/wiki/Greenspun's_Tenth_Rule"&gt;Greenspun's Tenth Rule&lt;/a&gt;:
&lt;blockquote&gt;
Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp
&lt;/blockquote&gt;
and I thought that my programs follow a similar pattern with dependent types: I'm always simulating them informally. Based on Section 6.1: "The Trouble with Faking It" in &lt;a href="http://www.cs.nott.ac.uk/~ctm/"&gt;Conor McBride&lt;/a&gt;'s &lt;a href="http://www.cs.nott.ac.uk/~ctm/faking.ps.gz"&gt;Faking It (Simulating Dependent Types in Haskell)&lt;/a&gt; (&lt;a href="http://citeseer.ist.psu.edu/mcbride01faking.html"&gt;mirror&lt;/a&gt;),  I wonder if there's any truth to something we might call
&lt;dl&gt;
&lt;dt&gt;Conor's Rule&lt;/dt&gt;
&lt;dd&gt;Any sufficiently complicated Haskell or ML program contains an ad hoc, informally-specified, bug-ridden, half-completed simulation of dependent types.&lt;/dd&gt;
&lt;/dl&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-4220869469690788347?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/4220869469690788347/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=4220869469690788347' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/4220869469690788347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/4220869469690788347'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/02/conors-rule.html' title='Conor&apos;s Rule?'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-2430773511442441263</id><published>2007-02-10T07:13:00.000-08:00</published><updated>2008-03-23T16:40:47.496-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='parallel or'/><category scheme='http://www.blogger.com/atom/ns#' term='CPOs'/><category scheme='http://www.blogger.com/atom/ns#' term='_|_'/><category scheme='http://www.blogger.com/atom/ns#' term='definability'/><category scheme='http://www.blogger.com/atom/ns#' term='continuity'/><title type='text'>Definability and Continuity</title><content type='html'>&lt;p&gt;In &lt;a href="http://japple.blogspot.com/2007/01/how-many-functions-are-there-of-type.html"&gt;How Many Functions are There of Type Bool -&amp;gt Bool?&lt;/a&gt;, I stated "The trick is to remember that if f is continuous, then f _|_ =/= _|_ implies that for all x, f x = f _|_". &lt;strong&gt;That is false&lt;/strong&gt;. It would have been true had I said "&amp;hellip; remember that if f is &lt;ins&gt;definable in Haskell&lt;/ins&gt;, then &amp;hellip;". The correct statement for continuous functions is: for all x, f x &amp;ge; f _|_. The "&amp;ge;" here is that used in domain theory to talk about &lt;acronym title="Complete Partial Order"&gt;CPO&lt;/acronym&gt;s.&lt;/p&gt;

&lt;p&gt;In addition to only considering functions definable in Haskell, I was also only considering &lt;dfn&gt;flat&lt;/dfn&gt; CPOs, in which each element is comparable only to itself and _|_. An example of a CPO that is not flat:
&lt;pre&gt;
data Wrap = Wrap Unit
data Unit = Unit
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;In the CPO Wrap&lt;sub&gt;_|_&lt;/sub&gt;, _|_ &amp;lt; Wrap _|_ &amp;lt; Wrap Unit. Though Wrap&lt;sub&gt;_|_&lt;/sub&gt; has three values, just like Bool&lt;sub&gt;_|_&lt;/sub&gt;, there are only nine functions (continuous or definable in Haskell) of type Wrap&lt;sub&gt;_|_&lt;/sub&gt; -&amp;gt; Bool&lt;sub&gt;_|_&lt;/sub&gt;. Furthermore, there are eleven continuous functions of type Wrap&lt;sub&gt;_|_&lt;/sub&gt; -&amp;gt; Wrap&lt;sub&gt;_|_&lt;/sub&gt;, and all are definable in Haskell. (Thanks to Stefan O'Rear for pointing that out).&lt;/p&gt;

&lt;p&gt;Clearly, the codomain isn't treated opaquely as it was in the last post: in order to count functions, we need to know the ordering on the codomain.
&lt;/p&gt;
&lt;p&gt;
I have some more thinking to do about counting, continuity, and definability before I can make any more assertions about the cardinality of function types.&lt;/p&gt;
&lt;h6&gt;Update:&lt;/h6&gt;
&lt;p&gt;
Stefan O'Rear pointed out an error in which I claimed certain functions were not definable in Haskell, when they actually are. A better example of a function that is continuous but not definable in Haskell is:
&lt;pre&gt;
parallel_or _ True = True
parallel_or True _ = True
parallel_or False False = False
&lt;/pre&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-2430773511442441263?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/2430773511442441263/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=2430773511442441263' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2430773511442441263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2430773511442441263'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/02/definability-and-continuity.html' title='Definability and Continuity'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-8260171635663747419</id><published>2007-02-07T19:27:00.000-08:00</published><updated>2008-01-28T21:31:44.698-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Simulating Dependent Types with Guarded Algebraic Datatypes'/><category scheme='http://www.blogger.com/atom/ns#' term='GADTs'/><category scheme='http://www.blogger.com/atom/ns#' term='OOP'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>C++ and GADTs</title><content type='html'>&lt;p&gt;
I just noticed &lt;a href="http://ken.friislarsen.net/blog/2005/03/03/gadt-in-c/"&gt;this post about GADTs in C++&lt;/a&gt;. It's more about C++'s warts than GADTs, but it's interesting nonetheless.
&lt;/p&gt;

&lt;p&gt;
I also noticed recently, while preparing for my upcoming talk at the &lt;a href="http://www.cs.virginia.edu/theory/"&gt;theory lunch&lt;/a&gt; (&lt;a href="http://www.cs.virginia.edu/~ils9d/theory/"&gt;mirror&lt;/a&gt;, &lt;a href="http://www.cs.virginia.edu/theory/spring2007.html"&gt;suspected future permalink, presently 404&lt;/a&gt;), that because the constructors in the OOP version of GADTs each get their own class, the class name can function as the constructor tag. This leads to what is called the &lt;a href="http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern"&gt;Curiously Recurring Template Pattern&lt;/a&gt; in C++. Example:
&lt;table border=1 style=solid padding=5&gt;
&lt;tr&gt;
&lt;th&gt;
Haskell
&lt;/th&gt;
&lt;th&gt;
C++
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre&gt;
data Nat t where
    Z :: Nat ZTag
    S :: Nat n -&gt; Nat (STag n)
data ZTag
data STag n
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;
template&amp;lt;class T&amp;gt;
class nat {};

class zero : nat&amp;lt;zero&amp;gt; {};

template&amp;lt;class N&amp;gt;
class succ : nat&amp;lt;succ&amp;lt;N&amp;gt; &amp;gt; {
public:
  succ&amp;lt;N&amp;gt;(nat&amp;lt;N&amp;gt; x) : pred(x) {}
  nat&amp;lt;N&amp;gt; pred;
};
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;
Of course, the tags in the Haskell version could have the same names as the constructors, since the constructor and type namespaces in Haskell are disjoint, but they would still have distinct meanings, unlike in the C++ code.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-8260171635663747419?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/8260171635663747419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=8260171635663747419' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8260171635663747419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8260171635663747419'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/02/c-and-gadts.html' title='C++ and GADTs'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-5552150220892085085</id><published>2007-02-05T15:48:00.000-08:00</published><updated>2008-03-23T16:47:43.577-07:00</updated><title type='text'>Types Feed</title><content type='html'>I have added to the sidebar a feed for the blogs I read about types. I made this feed using &lt;a href="http://www.google.com/reader/"&gt;Google reader&lt;/a&gt;, which also prepared a &lt;a href="http://www.google.com/reader/shared/user/11750803607670674155/label/types"&gt;blog-like interface&lt;/a&gt; and an &lt;a href="http://www.google.com/reader/public/atom/user/11750803607670674155/label/types"&gt;atom feed&lt;/a&gt;. Some of my posts will be appearing in the feed, since I both read and am an inhabitant of &lt;a href="http://planet.haskell.org"&gt;Planet Haskell&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-5552150220892085085?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/5552150220892085085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=5552150220892085085' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/5552150220892085085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/5552150220892085085'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/02/types-feed.html' title='Types Feed'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-5342744934644529458</id><published>2007-02-04T07:57:00.000-08:00</published><updated>2008-03-23T16:35:09.872-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Simulating Dependent Types with Guarded Algebraic Datatypes'/><category scheme='http://www.blogger.com/atom/ns#' term='sized lists'/><category scheme='http://www.blogger.com/atom/ns#' term='copious free time'/><title type='text'>If I Had Time</title><content type='html'>&lt;p&gt;Projects I would work on if I had time:
&lt;ul&gt;
&lt;li&gt;On &lt;a href="http://www.cs.virginia.edu/~jba5b/singleton/"&gt;Simulating Dependent Types with Guarded Algebraic Datatypes&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;Automatic lambda lifting for the &lt;a href="http://www.cs.virginia.edu/~jba5b/singleton/Haskell.hs"&gt;Haskell syntax&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Automatic printing of Scala and C# syntax&lt;/li&gt;
&lt;li&gt;A lambdabot plugin for lifting types, using GHC-as-a-library.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Sized lists:
&lt;ul&gt;
&lt;li&gt;Make a cabal-ized, hackage-d sized lists library.&lt;/li&gt;
&lt;li&gt;Automatically translate the &lt;a href="http://einstein.dsic.upv.es/nofib-buggy/"&gt;buggy NoFib benchmarks&lt;/a&gt; to using sized lists to see if the bugs get caught by the type checker.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://japple.blogspot.com/2007/02/missing-morphisms.html"&gt;Write Data.Scannable and &lt;code&gt;instance Foldable ((-&amp;gt;) a)&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-5342744934644529458?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/5342744934644529458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=5342744934644529458' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/5342744934644529458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/5342744934644529458'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/02/if-i-had-time.html' title='If I Had Time'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-2364237325163891779</id><published>2007-02-03T19:52:00.000-08:00</published><updated>2008-03-23T16:49:58.058-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='morphisms'/><title type='text'>Missing Morphisms</title><content type='html'>&lt;p&gt;
I'm a fan of &lt;a href="http://www.haskell.org/ghc/dist/current/docs/libraries/base/Data-Foldable.html"&gt;Data.Foldable&lt;/a&gt;, and I wonder if it could be extended to function types by way of &lt;a href="http://citeseer.ist.psu.edu/293490.html"&gt;Bananas in Space: Extending Fold and Unfold to Exponential Types&lt;/a&gt; (&lt;a href="http://www.cs.nott.ac.uk/~gmh//bananas.ps"&gt;mirror&lt;/a&gt;) or &lt;a href="http://repository.upenn.edu/cis_reports/43/"&gt;Boxes Go Bananas: Encoding Higher-Order Abstract Syntax with Parametric Polymorphism&lt;/a&gt; (&lt;a href="http://www.seas.upenn.edu/%7Esweirich/abstracts.html#washburn+:bgb-journal"&gt;mirror&lt;/a&gt;).
&lt;/p&gt;

&lt;p&gt;
Second, I understand that it may not be possible to give simple types to &lt;a href="http://citeseer.ist.psu.edu/meijer91functional.html"&gt;anamorphisms or hylomorphisms&lt;/a&gt; (&lt;a href="http://wwwhome.cs.utwente.nl/~fokkinga/mmf91m.ps"&gt;mirror&lt;/a&gt;), but I don't see there can't be a Data.Scannable with paramorphisms.
&lt;/p&gt;

&lt;p&gt;
Finally, I'm not even so sure that we can't give all of the bananas, lenses, envelopes and barbed wire generic (but more strongly typed than &lt;a href="http://www.haskell.org/ghc/dist/current/docs/libraries/base/Data-Generics-Basics.html"&gt;SYB&lt;/a&gt;) interfaces for even non-regular datatypes with &lt;a href="http://crab.rutgers.edu/~pjohann/tlca07-rev.pdf"&gt;initial algebra semantics&lt;/a&gt; (&lt;a href="http://www.cs.nott.ac.uk/~nxg/Tlca07.hs"&gt;code here&lt;/a&gt;).
&lt;/p&gt;

&lt;h6&gt;Update:&lt;/h6&gt;
&lt;p&gt;I think the first and second questions above are worth bothering the Haskell libaries mailing list about, so I did: &lt;a href="http://permalink.gmane.org/gmane.comp.lang.haskell.libraries/6218"&gt;Paramorphisms / Data.Scanable?&lt;/a&gt; (&lt;a href="http://www.haskell.org/pipermail/libraries/2007-February/006849.html"&gt;mirror&lt;/a&gt;), &lt;a href="http://permalink.gmane.org/gmane.comp.lang.haskell.libraries/6217"&gt;Catamorphisms for arrows?&lt;/a&gt; (&lt;a href="http://www.haskell.org/pipermail/libraries/2007-February/006848.html"&gt;mirror&lt;/a&gt;). As before, I expect I'll have to &lt;a href="http://japple.blogspot.com/2007/01/bug-reporting.html"&gt;push harder&lt;/a&gt; (by actually writing some code) if I want any changes made.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-2364237325163891779?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/2364237325163891779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=2364237325163891779' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2364237325163891779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2364237325163891779'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/02/missing-morphisms.html' title='Missing Morphisms'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-6770736201775450370</id><published>2007-02-03T12:30:00.000-08:00</published><updated>2008-03-23T16:33:30.571-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='V=L'/><category scheme='http://www.blogger.com/atom/ns#' term='countability'/><category scheme='http://www.blogger.com/atom/ns#' term='constructive logic'/><category scheme='http://www.blogger.com/atom/ns#' term='ordinals'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Countable Ordinals in Haskell</title><content type='html'>&lt;p&gt;
In &lt;a href="http://www.randomhacks.net/articles/2007/02/02/divide-infinity-by-2"&gt;Haskell: What happens when you divide infinity by 2?&lt;/a&gt;, Eric Kidd asks:
&lt;/p&gt;
&lt;blockquote&gt;
...&lt;br&gt;
2. Is it possible to represent any other (more interesting and/or more correct) definitions of infinity in Haskell?&lt;br&gt;
3. What’s the best way to think about the infinite ordinals?&lt;br&gt;
&lt;/blockquote&gt;

&lt;p&gt;The code below is my answer to those questions for countable ordinals only. I'm not sure if it makes sense to talk about representing uncoutable sets on the kind of computers we have now: We can talk about infinite countable sets as computable limits of finite objects, but what would an uncountable set look like? They can't be objects of &lt;code&gt;Nat -&amp;gt; Bool&lt;/code&gt;, since every object of this type is represented in some finite number of bits. It seems like we are stuck in a universe where Goedel's &lt;a href="http://en.wikipedia.org/wiki/Axiom_of_constructibility"&gt;V=L&lt;/a&gt; is true.&lt;/p&gt;
&lt;pre&gt;
{-# OPTIONS_GHC -fglasgow-exts #-}

{- See:
  http://en.wikipedia.org/wiki/Ordinal_arithmetic
  http://en.wikipedia.org/wiki/Large_countable_ordinals

  To add later:
  http://citeseer.ist.psu.edu/487179.html
-}


module Countable where

data Finite = Z
           | S !Finite

{- A countable ordinal is 0, a successor, or a limit of a countable
  sequence. This definition is weak, as the countable sequence should
  be strictly increasing, but that's hard to express. One way to do so
  would be to interpret (Limit f) as the limit of
  (sum i = 0 to n) (1 + f i). Note: this addition is not commutative.
  This would complicate things, however, so I'll leave it for a later
  extension.
-}
data Ordinal = Zero
            | Succ !Ordinal
            | Limit (Finite -&gt; Ordinal) deriving (Show)

{- I believe that there is no computable Eq or Ord instance for Ordinals.
  Comments?
 
  We make an approximation here by taking the nth value of the limit.
  This calculation is very slow, and, of course, will equate a lot of
  ordinals that are not actually equal.
-}

nth :: Ordinal -&gt; Finite -&gt; Integer
nth Zero _ = 0
nth (Succ x) n = 1+(nth x n)
nth (Limit f) n = nth (f n) n

instance Show (Finite -&gt; Ordinal) where
   show f = show [f Z,
                  f (S Z),
                  f (S (S Z)),
                  f (S (S (S Z)))]

instance Eq Ordinal where
   x == y = (show x) == (show y)

{- The basic ordinal arithmetic. Addition and multiplication are not
  commutative.
-}
addOrdinal :: Ordinal -&gt; Ordinal -&gt; Ordinal
addOrdinal x Zero = x
addOrdinal x (Succ y) = Succ (addOrdinal x y)
addOrdinal x (Limit y) = Limit (\z -&gt; addOrdinal x (y z))

multiplyOrdinal :: Ordinal -&gt; Ordinal -&gt; Ordinal
multiplyOrdinal x Zero = Zero
multiplyOrdinal x (Succ y) = addOrdinal (multiplyOrdinal x y) x
multiplyOrdinal x (Limit y) = Limit (\z -&gt; multiplyOrdinal x (y z))

expOrdinal :: Ordinal -&gt; Ordinal -&gt; Ordinal
expOrdinal x Zero = Succ Zero
expOrdinal x (Succ y) = multiplyOrdinal (expOrdinal x y) x
expOrdinal x (Limit y) = Limit (\z -&gt; expOrdinal x (y z))

-- The first infinite ordinal
finite :: Finite -&gt; Ordinal
finite Z = Zero
finite (S x) = Succ (finite x)

omega = Limit finite

-- Apply a f some number of times, starting at z
apply Zero f z = z
apply (Succ n) f z = f (apply n f z)
apply (Limit g) f z = Limit (\x -&gt; apply (g x) f z)

-- With apply, we have more succinct definitions of arithmetic
addOrdinal' x y = apply y Succ x
multiplyOrdinal' x y = apply y (flip addOrdinal x) Zero
expOrdinal' x y = apply y (flip multiplyOrdinal x) (Succ Zero)

-- Enumerates the fixed points of a function.
fix Zero f = apply omega f Zero
fix (Succ n) f = apply omega f (Succ (fix n f))
fix (Limit g) f = Limit (\x -&gt; fix (g x) f)

-- Some larger ordinals:
epsilon n = fix n (expOrdinal omega)

-- The Veblen heirarchy:
veblen Zero b = expOrdinal omega b
veblen (Succ a) b = fix b (veblen a)
veblen (Limit a) b = Limit (\x -&gt; veblen (a x) b)

-- Feferman-Schutte ordinals
gamma n = fix n (flip veblen Zero)
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-6770736201775450370?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/6770736201775450370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=6770736201775450370' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/6770736201775450370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/6770736201775450370'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/02/countable-ordinals-in-haskell.html' title='Countable Ordinals in Haskell'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-6007229537028907820</id><published>2007-01-29T18:30:00.000-08:00</published><updated>2007-01-29T19:00:50.520-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GADTs'/><category scheme='http://www.blogger.com/atom/ns#' term='quotient types'/><category scheme='http://www.blogger.com/atom/ns#' term='lightweight static capabilities'/><title type='text'>Quotient Types for Information Hiding</title><content type='html'>&lt;p&gt;
Imagine you're writing a datatype for representing sets. You want to hide the internal representation of sets from clients, but you also want to allow clients to perform any operations as efficiently as if the internal representation were exposed. This is not easy, and it's why &lt;a href="http://www.haskell.org/ghc/dist/current/docs/libraries/base/Data-Set.html"&gt;Data.Set&lt;/a&gt; has 36 functions, when all that are really needed to ensure the meaning of a set ("These elements are distinct") are &lt;code&gt;toList&lt;/code&gt; and &lt;code&gt;fromList&lt;/code&gt;. Of course, writing &lt;code&gt;member :: Ord a =&gt; a -&gt; Set a -&gt; Bool&lt;/code&gt; as

&lt;pre&gt;member x y = Data.List.elem x (toList y)&lt;/pre&gt;

is just awful, but the price we pay for efficient &lt;code&gt;member&lt;/code&gt; is having to open up the module and break the abstraction if one of the 34 other functions doesn't do exactly what we want. In addition to this pain, there's some danger: functions like &lt;code&gt;mapMonotonic&lt;/code&gt; are not really safe, and cannot be made so.

&lt;div style="float: right; padding: 1em; border: solid 0.1em; width : 40%;"&gt;
&lt;p&gt;
The papers I've been reading about quotient types:
&lt;ul&gt;
&lt;li&gt; Bart Jacobs' &lt;a href="http://citeseer.ist.psu.edu/jacobs94quotients.html"&gt;Quotients in Simple Type Theory&lt;/a&gt;
&lt;li&gt; Aleksey Nogin's &lt;a href="http://nogin.org/papers/quotients.html"&gt;Quotient Types: A Modular Approach.&lt;/a&gt; (&lt;a href="http://metaprl.org/papers/quotients.html"&gt;mirror 1&lt;/a&gt;, &lt;a href="http://citeseer.ist.psu.edu/578798.html"&gt;mirror 2&lt;/a&gt;)
&lt;/ul&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
We could alleviate all of this mess with quotient types. Quotient types allow modules to expose their internals with no danger of breaking abstractions. The &lt;q&gt;quotients&lt;/q&gt; are the same as the mathematical quotients in abstract algebra, where they are used frequently. Back on the type theory side, the elimination rule for typing quotients depends not just on types, but on terms, and so requires a type system with dependent types. That's a shame, since dependent types are so tricky to typecheck. It would be great if there were some form of lightweight quotient types that didn't require the full power of dependent types.

&lt;p&gt;
The break-the-abstraction vs. lose-efficiency-&amp;amp;-safety issue reminds me of the difference between GADTs and &lt;a href="http://okmij.org/ftp/Computation/lightweight-dependent-typing.html#Lightweight"&gt;lightweight static capabilities&lt;/a&gt;: &lt;a href="http://www.haskell.org/pipermail/haskell-cafe/2007-January/021178.html"&gt;GADTs are verbose&lt;/a&gt;, but &lt;a href="http://www.haskell.org/pipermail/haskell-cafe/2007-January/021349.html"&gt;they allow the client to safely and efficently operate on datatypes in ways that aren't covered by the library.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-6007229537028907820?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/6007229537028907820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=6007229537028907820' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/6007229537028907820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/6007229537028907820'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/01/quotient-types-for-information-hiding.html' title='Quotient Types for Information Hiding'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-5610608285458906904</id><published>2007-01-29T17:18:00.000-08:00</published><updated>2008-03-23T16:52:19.448-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='_|_'/><title type='text'>How Many Functions are There of Type Bool -&gt; Bool?</title><content type='html'>&lt;h6&gt;This post is incorrect. See &lt;a href="http://japple.blogspot.com/2007/02/definability-and-continuity.html"&gt;the corrections&lt;/a&gt;.&lt;/h6&gt;

&lt;p&gt;
&lt;del&gt;
Or, rather, how many continuous functions are there of type Bool&lt;sub&gt;_|_&lt;/sub&gt; -&amp;gt; Bool&lt;sub&gt;_|_&lt;/sub&gt;? I count 11, which seems like a strange number. The trick is to remember that if f is continuous, then f _|_ =/= _|_ implies that for all x, f x = f _|_. This gives us only two functions which take _|_ to non-_|_:
&lt;/del&gt;

&lt;p&gt;&lt;del&gt;
&lt;code&gt;
one = const True&lt;br&gt;
two = const False
&lt;/code&gt;
&lt;/del&gt;

&lt;p&gt;
&lt;del&gt;
The rest of the continuous functions fill the space Bool -&amp;gt; Bool&lt;sub&gt;_|_&lt;/sub&gt;. Since Bool&lt;sub&gt;_|_&lt;/sub&gt; is of size 3, there are 3&lt;sup&gt;2&lt;/sup&gt; remaining functions, which gives us 9+2 = 11 functions.
&lt;/del&gt;

&lt;p&gt;
&lt;del&gt;
We can generalize to say that A&lt;sub&gt;_|_&lt;/sub&gt; -&amp;gt; B&lt;sub&gt;_|_&lt;/sub&gt; has |B| + (|B|+1)&lt;sup&gt;|A|&lt;/sup&gt; inhabitants.
&lt;/del&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-5610608285458906904?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/5610608285458906904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=5610608285458906904' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/5610608285458906904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/5610608285458906904'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/01/how-many-functions-are-there-of-type.html' title='How Many Functions are There of Type Bool -&gt; Bool?'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-8824831540619263370</id><published>2007-01-20T17:34:00.000-08:00</published><updated>2008-03-23T16:56:11.647-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bugs'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><category scheme='http://www.blogger.com/atom/ns#' term='GHC'/><title type='text'>Bug Reporting</title><content type='html'>&lt;p&gt;A few months ago, I posted &lt;a href="http://thread.gmane.org/gmane.comp.lang.haskell.cafe/15348/focus=15348"&gt;a quandary to haskell-cafe about seemingly ineffable types in GHC&lt;/a&gt;: for a certain term, the type inferred by GHCi could not simply be listed in the source code, as this would cause the type checker to complain. I didn't get any bites on my post, and I chalked it up to some complications I didn't understand and no one had time to explain, and I went on to thinking about other things.

&lt;p&gt;Last year, I graded a C++ assignment for a class at the local university (and my alma mater). We required the use of std::set, and a student noticed that he could modify the value of a member of a std::set&lt;T&gt; in place, and the compiler wouldn't complain.

&lt;p&gt;Both of these turn out to be bugs, &lt;a href="http://hackage.haskell.org/trac/ghc/ticket/1111"&gt;in GHC&lt;/a&gt; and &lt;a href="http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#103"&gt;in  the C++ standard&lt;/a&gt;. The lessons I've learned about programming languages:
&lt;ol&gt;
&lt;li&gt; If something doesn't make sense, investigate. If it turns out you just don't understand something that is the way it is for complicated reasons, you still will have learned something useful.
&lt;li&gt; The squeaky wheel gets the grease. I asked the Haskell Cafe about the GHC infelicity, but didn't inquire at the GHC-specific mailing lists, and I didn't keep asking when nobody responded.
&lt;li&gt; When you see something funny looking, don't just ask people why it's funny looking. Instead, push things to their logical conclusion, and find a test case that's obviously wrong. This will give people a reason to listen to you.
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-8824831540619263370?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/8824831540619263370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=8824831540619263370' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8824831540619263370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8824831540619263370'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/01/bug-reporting.html' title='Bug Reporting'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-2242174494152628119</id><published>2007-01-19T17:22:00.000-08:00</published><updated>2008-03-23T16:54:05.406-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GHC'/><title type='text'>Foralls, Redexes, and Type Lambdas</title><content type='html'>&lt;a href="http://japple.blogspot.com/2007/01/foralls-kinds-with-arrows-and.html"&gt;In my last post about universally quantified types&lt;/a&gt;, I was asking why GHC disallows datatypes like &lt;code&gt;Evil&lt;/code&gt; while allowing datatypes like &lt;code&gt;Fine&lt;/code&gt;:

&lt;pre&gt;data OK (x :: * -&gt; *) where
   OK :: OK x
type Fine = OK Maybe
type Evil = OK (forall (f  :: * -&gt; *) . f)&lt;/pre&gt;

This seems more confusing when &lt;code&gt;Evil'&lt;/code&gt; is just fine:

&lt;pre&gt;data OK' (x :: *) where
   OK' :: OK' x
type Fine' = OK' Int
type Evil' = OK' (forall (f  :: *) . f)&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://www.cs.rutgers.edu/~ccshan/"&gt;Ken Shan&lt;/a&gt; answered my question: In the static semantics of the typed lambda calculus, only forms like (&amp;Lambda;t:k.r) @ s are redexes. This makes sense to me, but it seems like it's so for simplicity reasons.  I expect that this makes the metatheory simpler.

&lt;p&gt;Unfortunately, this makes some things in GHC a pain, since GHC doesn't have type lambdas. &lt;a href="http://www.mail-archive.com/haskell@haskell.org/msg10623.html"&gt;SPJ suggests that this is because it makes unification for type inference impossible&lt;/a&gt;, but I don't yet understand why. &lt;a href="http://www.cs.uu.nl/wiki/Ehc/LanguageFeatures"&gt;The feature list for EHC indicates that it does support type lambdas&lt;/a&gt;, though I haven't tested this.

&lt;h6&gt;Update: (29 Jan 2007)&lt;/h6&gt;
&lt;p&gt; &lt;a href="http://research.microsoft.com/~simonpj/papers/history-of-haskell/index.htm"&gt;A History of Haskell&lt;/a&gt; points to &lt;a href="http://web.cecs.pdx.edu/~mpj/pubs/fpca93.html"&gt;A system of constructor classes&lt;/a&gt; (&lt;a href="http://citeseer.ist.psu.edu/jones95system.html"&gt;mirror&lt;/a&gt;) regarding unification and type lambdas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-2242174494152628119?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/2242174494152628119/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=2242174494152628119' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2242174494152628119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/2242174494152628119'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/01/foralls-redexes-and-type-lambdas.html' title='Foralls, Redexes, and Type Lambdas'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-8124053052614549120</id><published>2007-01-15T18:58:00.000-08:00</published><updated>2008-03-23T16:57:17.548-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='impredicativity'/><category scheme='http://www.blogger.com/atom/ns#' term='kinds'/><category scheme='http://www.blogger.com/atom/ns#' term='Fomega'/><title type='text'>Foralls, Kinds with Arrows, and Impredicativity (?)</title><content type='html'>I can't figure out why the kinding rule for universal quantification in F&lt;sub&gt;&amp;omega;&lt;/sub&gt; is:

&lt;pre&gt;           C, x : k1 |- y : *
(1)    -----------------------------
       C |- (\forall x : k1 . y) : *&lt;/pre&gt;

That is, why the type inside the universal quantification must be of kind &lt;code&gt;*&lt;/code&gt;.
&lt;p&gt;
I would expect the rule to be

&lt;pre&gt;            C, x : k1 |- y : k2
(1')    ------------------------------
        C |- (\forall x : k1 . y) : k2&lt;/pre&gt;

Using (1), I can still get

&lt;pre&gt;              C, x : k1 |- y : * -&gt; *
(2)    ------------------------------------------------------
       C |- (\Lambda z : * . \forall x : k1 . y @ z) : * -&gt; *&lt;/pre&gt;

by eta-expansion, so using (1) instead of (1') doesn't seem to reduce the available power, it just makes the notation more annoying.
&lt;p&gt;
I suspect that the reason for (1) instead of (1') has something to do with impredicativity, since (1) is only valid in impredicative systems anyway.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-8124053052614549120?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/8124053052614549120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=8124053052614549120' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8124053052614549120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/8124053052614549120'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/01/foralls-kinds-with-arrows-and.html' title='Foralls, Kinds with Arrows, and Impredicativity (?)'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-3954213236753908276</id><published>2007-01-15T18:49:00.000-08:00</published><updated>2008-03-23T16:55:49.019-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='constructive logic'/><title type='text'>Non-constructive Proofs and Programming</title><content type='html'>Two excellent examples of programming with non-constructive proofs are given in &lt;a href="http://www.doc.ic.ac.uk/%7Esvb/CLaC/Papers/936f41e5c3803a1cf9e681475c2e.pdf"&gt;Simplifying Programs Extracted from Classical Proofs&lt;/a&gt; by Yevgeniy Makarov. The examples they give are better than the immediate example I think of: the proof that there are some two irrational numbers x and y such that x&lt;sup&gt;y&lt;/sup&gt; is rational. This proof is simple to do, but requires some heavy background machinery for rational and irrational numbers. Perhaps I could code this proof by using _|_ for the theorems about rational numbers that I know to be true, but don't wish to prove.
&lt;p&gt;
The other two examples of simple non-constructive proofs that I think of are the irrationality of the square root of 2 and the infinitude of the primes. Of course, those are usually stated in non-constructive ways, but they are actually constructive with only a slight bit of tweaking. I haven't read enough of the Makarov paper to see if the simplifications proposed would turn these non-constructive proofs into constructive ones.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-3954213236753908276?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/3954213236753908276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=3954213236753908276' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/3954213236753908276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/3954213236753908276'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/01/non-constructive-proofs-and-programming.html' title='Non-constructive Proofs and Programming'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-3737889011034547610</id><published>2007-01-13T12:54:00.000-08:00</published><updated>2008-03-23T16:44:40.791-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='termination'/><category scheme='http://www.blogger.com/atom/ns#' term='constructive logic'/><category scheme='http://www.blogger.com/atom/ns#' term='Dependent ML'/><title type='text'>Non-constructive Proofs and Productivity</title><content type='html'>&lt;p&gt;
Languages in the &lt;a href="http://www.cs.bu.edu/~hwxi/"&gt;Dependent ML family&lt;/a&gt; allow users to ensure termination by using a &lt;em&gt;termination metric&lt;/em&gt;, a number that is strictly decreasing on recursive calls in the definition of the function.

&lt;p&gt;
There is a counterpart to termination for co-recursive structures, where we need to show that a function produces values indefinitely. So, for the &lt;a href="http://en.wikipedia.org/wiki/Collatz_conjecture"&gt;Collatz conjecture&lt;/a&gt;, we want to show termination for:

&lt;pre&gt;collatz n = collatz' n []
collatz' 1 r = 1:r
collatz' n r =
    if n `mod` 2 == 0
    then collatz' (n `div` 2) (n:r)
    else collatz' (3*n + 1) (n:r)&lt;/pre&gt;

But for the &lt;a href="http://en.wikipedia.org/wiki/Twin_prime_conjecture"&gt;twin prime conjecture&lt;/a&gt; we want to show the productivity of:

&lt;pre&gt;data Stream a = Stream a (Stream a)
twins = twins' 3
twins' n =
    if (primep n) &amp;&amp; (primep (n+2))
    then Stream (n,n+2) (twins' (n+2))
    else twins (n+2)&lt;/pre&gt;

&lt;p&gt;
I don't know if any of the members of the DML family can check productivity. Imagine they could, and imagine we had a non-constructive proof of the twin primes conjecture. Could we use that proof to allow a definition of &lt;code&gt;twins&lt;/code&gt; to be marked productive?

&lt;p&gt;
Most of the time, we talk about the Curry-Howard correspondence in reference to intuitionist logic and functional programming, but non-constructive proofs of productivity seem like a good way to be able to use more powerful logic in programming, since they don't have to change the implementation of the function they are attached to.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-3737889011034547610?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/3737889011034547610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=3737889011034547610' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/3737889011034547610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/3737889011034547610'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/01/non-constructive-proofs-and.html' title='Non-constructive Proofs and Productivity'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-3892387611438383498</id><published>2007-01-12T14:11:00.000-08:00</published><updated>2008-01-22T21:09:16.154-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='information flow'/><category scheme='http://www.blogger.com/atom/ns#' term='flow caml'/><title type='text'>Static Security Assurance From Afar</title><content type='html'>&lt;p&gt;I work at an e-commerce company. I was thinking today of how typed programming would make our code more reliable, and I began to wonder about using types (or other static assurance methods) to ensure that we don't accidentally reveal information to parties that shouldn't see it. I'm thinking here of the &lt;a href="http://web.archive.org/web/20061216215053rn_1/www.cis.upenn.edu/~stse/apollo/"&gt;Apollo project&lt;/a&gt; (specifically, &lt;a href="http://citeseer.ist.psu.edu/650196.html"&gt;Translating dependency into parametricity&lt;/a&gt;) or &lt;a href="http://cristal.inria.fr/%7Esimonet/soft/flowcaml/"&gt;Flow Caml&lt;/a&gt;. I don't see a way for us to use technology like this when working with other companies.

&lt;p&gt;
As an example, we might pass a customer's info to a third party site along with some identifying informaiton about us, to verify the third party that the customer is legit. How can I trust the third party site to not reveal our shared secret to the customer?

&lt;p&gt;
I suspect this is a problem for cryptographers, not type theorists. Since much of the information that we deliver to customers is tainted by using secrets to obtain it, static analysis wouldn't help maintain security.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-3892387611438383498?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/3892387611438383498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=3892387611438383498' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/3892387611438383498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/3892387611438383498'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/01/static-security-assurance.html' title='Static Security Assurance From Afar'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6839602.post-7593329855837516704</id><published>2007-01-11T15:46:00.000-08:00</published><updated>2008-03-23T16:54:21.695-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GADTs'/><category scheme='http://www.blogger.com/atom/ns#' term='type disequality'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Type (Dis)equality</title><content type='html'>Type equality is the essential ingredient in guarded algebraic datatypes:

&lt;pre&gt;data Z ; data S n ;

data ListGADT a n where
    NilListGADT :: ListGADT a Zero
    ConsListGADT :: a -&gt; ListGADT a n -&gt; ListGADT a (S n)

data TypeEqual a b = . . .
data ListEq a n = NilListEq (TypeEqual n Z)
                | forall m . ConsListEq (TypeEqual n (S m)) a (ListEq a m)&lt;/pre&gt;

What new power would type disequality bring? It might prevent infinite types.

&lt;pre&gt;data WrapList a = forall n . WrapList (ListGADT a n)

cons :: a -&gt; WrapList a -&gt; WrapList a
cons x (WrapList y) = WrapList (Cons x y)

ones = cons 1 ones&lt;/pre&gt;

Here, the size type inside ones is &lt;code&gt;S (S (S . . . &lt;/code&gt;. That's bad. What if we wrote:

&lt;pre&gt;data TypeDisEq a b where
    DisEqLess :: DisEq Z (S a)
    DisEqMore :: DisEq (S a) Z
    DisEqInduct :: DisEq a b -&gt; DisEq (S a) (S b)

data ListGADTDisEq a n where
    NilListGADTDisEq :: ListGADTDisEq a Zero
    ConsListGADTDisEq :: a -&gt; ListGADTDisEq a n -&gt; (TypeDisEq n (S n)) -&gt; ListGADTDisEq a (S n)&lt;/pre&gt;

Now, since the size type inside a &lt;code&gt;ListGADTDisEq&lt;/code&gt; can't be one more than itself, it's finite, and we might not be able to form &lt;code&gt;ones&lt;/code&gt;. Sadly, that's not true:

&lt;pre&gt;data WrapListDisEq a = forall n . WrapListDisEq (ListGADTDisEq a n)

cons' :: a -&gt; WrapListDisEq a -&gt; WrapListDisEq a
cons' x (WrapListDisEq NilListGADTDisEq) = WrapListDisEq (ConsListGADTDisEq x Nil DisEqBase)
cons' x (WrapListDisEq p@(Cons q r s)) = WrapListDisEq (ConsListGADTDisEq x p (DisEqInduct s))

ones' = cons' 1 ones'&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6839602-7593329855837516704?l=blog.jbapple.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.jbapple.com/feeds/7593329855837516704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6839602&amp;postID=7593329855837516704' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/7593329855837516704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6839602/posts/default/7593329855837516704'/><link rel='alternate' type='text/html' href='http://blog.jbapple.com/2007/01/type-disequality.html' title='Type (Dis)equality'/><author><name>Jim Apple</name><uri>http://www.blogger.com/profile/11080395413026172939</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='32' src='http://www.jbapple.com/me-in-suit.jpg'/></author><thr:total>0</thr:total></entry></feed>
