<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Mathematics and Computation</title>
	<atom:link href="http://math.andrej.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://math.andrej.com</link>
	<description>Mathematics for computers</description>
	<pubDate>Fri, 29 May 2009 08:13:09 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<item>
		<title>Mathematically Structured but not Necessarily Functional Programming</title>
		<link>http://math.andrej.com/2009/05/29/mathematically-structured-but-not-necessarily-functional-programming/</link>
		<comments>http://math.andrej.com/2009/05/29/mathematically-structured-but-not-necessarily-functional-programming/#comments</comments>
		<pubDate>Fri, 29 May 2009 06:16:18 +0000</pubDate>
		<dc:creator>Andrej Bauer</dc:creator>
		
		<category><![CDATA[Computation]]></category>

		<category><![CDATA[Constructive math]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[RZ]]></category>

		<category><![CDATA[Talks]]></category>

		<guid isPermaLink="false">http://math.andrej.com/?p=217</guid>
		<description><![CDATA[These are the slides and the extended abstract from my MSFP 2008 talk. Apparently, I forgot to publish them online. There is a discussion on the Agda mailing list to which the talk is somewhat relevant, so I am publishing now.
Abstract: Realizability is an interpretation of intuitionistic logic which subsumes the Curry-Howard interpretation of propositions [...]]]></description>
			<content:encoded><![CDATA[<p>These are the slides and the extended abstract from my <a href="http://msfp.org.uk/">MSFP</a> 2008 talk. Apparently, I forgot to publish them online. There is a discussion on the <a href="http://wiki.portal.chalmers.se/agda/">Agda</a> mailing list to which the talk is somewhat relevant, so I am publishing now.</p>
<p><strong>Abstract:</strong> Realizability is an interpretation of intuitionistic logic which subsumes the Curry-Howard interpretation of propositions as types, because it allows the realizers to use computational effects such as non-termination, store and exceptions. Therefore, we can use realizability as a framework for program development and extraction which allows any style of programming, not just the purely functional one that is supported by the Curry-Howard correspondence. In joint work with <a href="http://www.cs.hmc.edu/~stone/">Christopher A. Stone</a> we developed RZ, a tool which uses realizability to translate specifications written in constructive logic into interface code annotated with logical assertions. RZ does not extract code from proofs, but allows any implementation method, from handwritten code to code extracted from proofs by other tools. In our experience, RZ is useful for specification of non-trivial theories. While the use of computational effects does improve efficiency it also makes it difficult to reason about programs and prove their correctness. We demonstrate this fact by considering non-purely functional realizers for a Brouwerian continuity principle.</p>
<p><strong>Download: </strong><a href="/wp-content/uploads/2009/05/msfp2008-slides.pdf">msfp2008-slides.pdf</a>, <a href="/wp-content/uploads/2009/05/msfp2008-abstract.pdf">msfp2008-abstract.pdf</a></p>
]]></content:encoded>
			<wfw:commentRss>http://math.andrej.com/2009/05/29/mathematically-structured-but-not-necessarily-functional-programming/feed/</wfw:commentRss>
		</item>
		<item>
		<title>On programming language design</title>
		<link>http://math.andrej.com/2009/04/11/on-programming-language-design/</link>
		<comments>http://math.andrej.com/2009/04/11/on-programming-language-design/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 16:29:03 +0000</pubDate>
		<dc:creator>Andrej Bauer</dc:creator>
		
		<category><![CDATA[General]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://math.andrej.com/?p=194</guid>
		<description><![CDATA[In a recent post I claimed that Python&#8217;s lambda construct is broken. This attracted some angry responses by people who thought I was confused about how Python works. Luckily there were also many useful responses from which I learnt. This post is a response to comment 27, which asks me to say more about my [...]]]></description>
			<content:encoded><![CDATA[<p>In a recent post I claimed that <a href="/2009/04/09/pythons-lambda-is-broken/">Python&#8217;s lambda construct is broken</a>. This attracted <a href="/2009/04/09/pythons-lambda-is-broken/#comment-11485">some</a> <a href="/2009/04/09/pythons-lambda-is-broken/#comment-11486">angry</a> <a href="/2009/04/09/pythons-lambda-is-broken/#comment-11499">responses</a> by people who thought I was confused about how Python works. Luckily there were also many useful responses from which I learnt. This post is a response to <a href="/2009/04/09/pythons-lambda-is-broken/#comment-11501">comment 27</a>, which asks me to say more about my calling certain design decisions in Python crazy.</p>
<p><span id="more-194"></span>Language design is like architecture. The architect is bound by the rules of nature, he has to take into account the properties of the building materials, and he must never forget the purpose that the building will serve. Likewise, the designer of a programming language is bound by the theorems of computability theory, he must take into account the properties of the underlying hardware, and he must never forget that the language is used by programmers.</p>
<p>When I teach the theory of programming languages, I tell my students that there is a design principle from which almost everything else follows:</p>
<blockquote><p><em>&#8220;Programmers are just humans: forgetful, lazy, and they make every mistake imaginable.&#8221;</em></p></blockquote>
<p>Therefore, it is the task of the designer to make a programming language which counters these deficiencies. A language must not be too complex, lest the programmer forget half of it. A language must support the programmer&#8217;s laziness by providing lots of useful libraries, and by making it possible to express ideas directly and succinctly. The language must allow good organization of source code, otherwise the programmer will use the copy-paste method. The language must try really hard to catch programming mistakes, especially the mundane ones that happen to everyone all the time. When it finds a mistake, it must point to the true reason for it, preferably with an error message that humans understand.</p>
<p>You will notice that so far I have not said a word about efficiency. If this were the year 1972 we would talk about efficiency first and forget about the programmers, because 37 years ago hardware and processing time were the scarcest resources. Today we live in different times when the most expensive resource is development time. In 1972 it was a <em>good</em> design decision to implement arrays in C so that they did not carry with them information about their lengths (save a couple of bytes on each array), it was a <em>good</em> decision not to check for out-of-bounds errors in array indexing (save a couple of CPU cycles), and it was a <em>good</em> decision not to have garbage collection (it didn&#8217;t work well anyhow). From today&#8217;s point of view all these decisions were horrible mistakes. Buffer overflows, which are a consequence of missing out-of-bounds checks, cost the industry huge amounts of money every year, while lack of automated garbage collection results in memory leaks that cause programs to be unstable.</p>
<p>Of course, even today C might be just the right tool for your specific task. I am not saying that memory efficiency and speed are not important. They are not <em>as important</em> as they used to be. The first objective in a programming language design today should be friendliness to programmers. A lot is known about how to write an optimizing compiler and how to generate efficient code, so usually the design of the language does not prevent generation of efficient compiled or interpreted code.</p>
<p>People do not make bad design decisions because they are evil or stupid. They make them because they judge that the advantages of the decision outweigh the disadvantages. What they often do not see is that they could have achieved the same advantages in a different way, without introducing the disadvantages. Therefore, it is very important to get the order right: <em>first</em> make sure the design avoids the disadvantages, <em>then</em> think about how to get the advantages back.</p>
<p>Let us now apply these principles to several examples.</p>
<h3>Undefined values (NULL, null, undef, None)</h3>
<p>Suppose we want a language with references (pointers in C). The principle tells us that it is a bad idea to allow invalid references because programmers <em>will</em> create them. Indeed, most recently designed languages, say Java and Python, do not allow you to write obviously risky things, such as</p>
<blockquote>
<pre>int *p = (int *)0xabcdef;</pre>
</blockquote>
<p>Unfortunately, many designers have still not learnt that the special <code>NULL</code> pointer or <code>null</code> object is an equally bad idea. Python&#8217;s <code>None</code>, perl&#8217;s <code>undef</code>, and SQL&#8217;s <code>NULL</code> all fall in the same category. I can hear you list lots of advantages of having these. But stick to the principle: <code>NULL</code> is wrong because it causes horrible and tricky mistakes which appear even after the program was tested thoroughly. You cannot introduce <code>NULL</code> into the language and tell the programmer to be careful about it. The programmer is not capable of being careful! There is plenty of evidence to support this sad fact.</p>
<p>Therefore <em>NULL, null, None and undef must go.</em> I shall collectively denote these with Python&#8217;s <code>None</code>. Of course, if we take away None, we must put something else back in. To see what is needed, consider the fact that <code>None</code> is intended as a special constant that signifies &#8220;missing value&#8221;. Problems occur when a given value could be either &#8220;proper&#8221; or &#8220;missing&#8221; and the programmer forgets to consider the case of missing value. The solution is to design the language in such a way that the programmer is always forced to consider both possibilities.</p>
<p>For example, Haskell does this with the datatype <a href="http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Maybe"><code>Maybe</code></a>, which has two kinds of values:</p>
<ul>
<li><code>Nothing</code>, meaning &#8220;missing value&#8221;</li>
<li><code>Just x</code>, meaning &#8220;the value is <code>x</code>&#8220;</li>
</ul>
<p>The <em>only</em> way to use such a value in Haskell is to consider <em>both</em> cases, otherwise the compiler complains. The language is forcing the programmer to do the right thing. Is this annoying? You will probably feel annoyed if you are used to ugly hacks with <code>None</code>, but a bit of experience will quickly convince you that the advantages easily outweigh your tendency for laziness. By the way, Haskell actually supports your laziness. Once you tell it that the type of a value is <code>Maybe</code>, it will find for you all the places where you need to be careful about <code>Nothing</code>. C, Java, Python, and perl stay silent and let you suffer through your own mistaken uses of <code>NULL</code>&#8217;s, <code>null</code>&#8217;s, <code>None</code>&#8217;s, and <code>undef</code>&#8217;s.</p>
<p>Other languages that let you have the data type like Haskell&#8217;s <code>Maybe</code> are ML and Ocaml because they have <a href="http://en.wikipedia.org/wiki/Sum_type">sum types</a>. Pascal, Modula-2 and C have broken sum types because they require the programmer to handle the tag by hand.</p>
<h3>Everything is an object (or list, or array)</h3>
<p>Many languages are advertised as &#8220;simple&#8221; because in them everything is expressed with just a couple of basic concepts. Lisp and scheme programmers proudly represent all sorts of data with conses and lists. Fortran programmers implement linked lists and trees with arrays. In Java and Python &#8220;everything is an object&#8221;, more or less.</p>
<p>It is good to have a simple language, but it is not good to sacrifice its expressiveness to the point where most of the time the programmer has to encode the concepts that he really needs indirectly with those available in the language. Programmers cannot do such things reliably, and the compiler cannot help them with the task because it does not know what is in programmer&#8217;s head.</p>
<p>Let us look at a typical example in scheme. Suppose we would like to represent binary trees in which the nodes are labeled with integers. In scheme we might do this by representing the empty tree as <code>()</code>, and use a three-element list <code>(k l r)</code> to represent a tree whose root is labeled by <code>k</code>, the left subtree is <code>l</code>, and the right subtree is <code>r</code>. A <a href="http://www.google.si/search?q=scheme+binary+tree">quick search on Google</a> shows that this is a popular way of implementing trees in scheme. It&#8217;s simple, it&#8217;s cool, it&#8217;s easy to explain to the students, but scheme will have no idea whatsoever what you&#8217;re doing. There are a number of trivial mistakes which can be made with such a representation, and scheme won&#8217;t detect them (at best you will get a runtime error): you might write <code>(l k r)</code> instead of <code>(k l r)</code>, you might mistakenly pass a four-element list to a function expecting a tree, you might mistakenly think that the integer <code>42</code> is a valid representation of the tree <code>(42 () ())</code>, you might mistakenly try to compute the left subtree of the empty tree, etc. And remember, the programmer <em>will</em> make all these mistakes.</p>
<p>With objects the situation is somewhat better. In Java we would define a class Tree with three attributes <code>root</code>, <code>left</code>, and <code>right</code>. It will be impossible to build a tree with a missing attribute, or too many attributes. But we will hit another problem: how to represent the empty tree? There are several choices none of which is ideal:</p>
<ol>
<li>the empty tree is <code>null</code>: this is the worst solution, as any Java programmer knows</li>
<li>we define a class <code>Tree</code> and subclasses <code>EmptyTree</code> and <code>NodeTree </code>represent the two different kinds of tree</li>
<li>we add a fourth attribute <code>empty</code> of type boolean which tells us whether the tree is empty</li>
</ol>
<p>There are probably other options. The first solution is horrible, as every Java programmer knows, because it leads to many <code>NullPointerExceptions</code>. The second solution is probably the most &#8220;object-orientedly correct&#8221; but people find it impractical, as it spreads code around in two classes. When I taught java I lectured the third solution, but that one has the big disadvantage that the programmer is responsible for checking every time whether a tree is empty or not.</p>
<p>A decent programming language should help with the following common problems regarding binary trees:</p>
<ol>
<li>Prevent the construction of an invalid tree, such as one with missing parts, or dangling pointers.</li>
<li>Prevent <em>at compile time</em> access to a component which is not there. For example, the compiler should detect the fact that the programmer is trying to access the left subtree of the empty tree.</li>
<li>Make sure the programmer never forgets to consider both possibilities&#8211;the empty tree and the non-empty tree.</li>
</ol>
<p>The above scheme representation does not help with the first problem. A C implementation with pointers would allow dangling pointers. An object-oriented solution typically won&#8217;t help with the second and the third problems.</p>
<p>You might wonder what it is that I want. The answer is that the programming language should have built-in <em>inductive data types</em>, because that&#8217;s what binary trees are. In Haskell, which has inductive data types, trees are defined directly in terms of their structure:</p>
<blockquote>
<pre>data Tree = Empty | Node Int Tree Tree</pre>
</blockquote>
<p>This expresses the definition of trees <em>directly</em>: a tree is either empty or a node composed of an integer and two trees. Haskell will be able to catch all the common problems listed above. Other languages supporting this sort of definition are ML, Ocaml, F#, and interestingly Visual Prolog (I am told by Wikipedia).</p>
<p>We might ask for more. Suppose we wanted to implement <a href="http://en.wikipedia.org/wiki/Binary_search_tree">binary search trees</a>. Then we would require that the left subtree only contains nodes that are smaller than the root, and the right subtree only nodes that are larger than the root. Can a programming language be designed so that this property is guaranteed? Yes, for example the compiler could insert suitable checks into the code so that anomalies are detected during execution as soon as they occur. This might be nice for debugging purposes, but what is production code supposed to do if it discovers an anomalous data structure during its execution? Ignore it? Raise an exception? It is much more useful to know <em>before</em> the program is run that the data structure will never be corrupted. Here we hit against a law of nature: there is no algorithm that would analyze an arbitrary piece of code and determine whether it will only produce valid search trees. It is a fact of life. If you really want to check that your programs are correct you will have to help the compiler. There are excellent tools for doing that, such as <a href="http://coq.inria.fr/">Coq</a> and <a href="http://wiki.portal.chalmers.se/agda/">Agda</a>&#8211;have a look to see how programmers might develop their code in the future.</p>
<h3>Confusing definitions and variables</h3>
<p>A <em>definition</em> binds an identifier to a particular <em>fixed</em> value. A <em>variable</em> or a <em>mutable value</em> is a memory location which holds a value that can be read and changed. These two notions should not be confused. Unfortunately, traditional programming languages only provide variables, so many programmers don&#8217;t even understand what definitions are. Java tries to fix this with the <a href="http://en.wikipedia.org/wiki/Final_(Java)">final</a> declaration, and C++ with the const declaration, but these are not used by programmers as much as they could be (which is a typical sign of dubious design decisions).</p>
<p>Using variables instead of definitions is wrong for a number of reasons. First, if the compiler knows which identifiers are bound to immutable values it can optimize the code better. It can, for example, decide to store the value in a register, or to keep around several copies without worrying about synchronization between them (think threaded applications). Second, if we allow the programmer to change a value which is supposed to be constant, then he will do so.</p>
<p>If you observe how variables are typically used, you will see several distinct uses:</p>
<ul>
<li>often a variable is only assigned to once and is used as an (immutable) definition</li>
<li>a variable in a loop or list comprehension ranges over the elements of a list, or a collection of objects</li>
<li>a variable stores the current state and is genuinely mutable</li>
</ul>
<p>Should loop counters be mutable? I think not. Code that changes the loop counter in the body of the loop is confusing and error prone. If you want to fiddle with counters, use the while loop instead. So in two out of three cases we want our variables to be immutable, but the popular programming languages only give us variables. That&#8217;s silly. We should design the language so that the <em>default</em> case is an immutable value. If the programmer wants a mutable value, he should say so explicitly. This is just the opposite of what Java and C++ do. An example of a language that is designed this way is <a href="http://en.wikipedia.org/wiki/Standard_ML">ML</a> and <a href="http://www.ocaml.org/">ocaml</a>. In Haskell you have to jump through hoops to get mutable values (now I am going to hear it from a monad aficionado, please spare me an unnecessary burst of anger).</p>
<h3>Out of scope variables</h3>
<p>I thought I would not have to explain why undefined identifiers are a bad a idea, but the reader in <a href="/2009/04/09/pythons-lambda-is-broken/#comment-11501">comment 27</a> explicitly asked about this.</p>
<p>If a programmer refers to an undefined name then an error should be reported. Concretely, I claimed that Python should complain about the following definition:</p>
<blockquote>
<pre>def f(n): return i + n</pre>
</blockquote>
<p>What is <code>i</code>? Pythonists will quickly point out that <code>i</code> will be defined later, and how deferred definitions are useful because they allows us to define mutually recursive functions. Indeed, Java and Haskell also accept mutually recursive definitions. But unlike Python they make sure that nothing is missing at the time of definition, whereas Python will only complain when the above function <code>f</code> is used. To be honest, Python kindly displays the correct error message showing that the trouble is with the definition of <code>f</code>. But why should this be a runtime error when the mistake can easily be detected at compile time? Actually, this question leads to a more general question, which I consider next.</p>
<h3>When should mistakes be discovered?</h3>
<p>Should programming bugs be discovered by the programmer or by the user? The answer seems pretty clear. Therefore, a language should be designed so that as many programming errors as possible are discovered early on, that is <em>before</em> the program is sent to the user. In fact, in order to speed up development (remember that the development time is expensive) the programmer should be told about errors without having to run the program and directing its execution to the place where the latest code change actually gets executed.</p>
<p>This philosophy leads to the design of <em>statically</em> checked languages. A typical feature of such a language is that all the types are known at compile time. In contrast, a dynamically typed languages checks the types during runtime. Java, Haskell and ocaml are of the former kind, scheme, javascript and Python of the latter.</p>
<p>There are situations in which a statically checked language is better, for example if you&#8217;re writing a program that will control a laser during eye surgery. But there are also situations in which maximum flexibility is required of a program, for example programs that are embedded in web pages. The web as we know it would not exist if every javascript error caused the browser to reject the entire web page (try finding a page on a major web site that does not have any javascript errors).</p>
<p>Let me also point out that <em>testing</em> cannot replace good language design. Testing is very important, but it should be used to discover problems that cannot be discovered earlier in the development cycle.</p>
<p>I used to think that statically checked languages are better for teaching because they prevent the students from doing obviously stupid things. About two years ago I changed my mind. The students learn much better by doing stupid things than by being told by an oppressive compiler that their programs are stupid. So this year I switched to Python. The students are happier, and so am I (because I don&#8217;t have to explain that code must be properly indented). Python does not whine all the time. Instead it lets them explore the possibilities, and by discovering which ones crash their programs they seem to understand better how the machine works.</p>
]]></content:encoded>
			<wfw:commentRss>http://math.andrej.com/2009/04/11/on-programming-language-design/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Python&#8217;s lambda is broken!</title>
		<link>http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/</link>
		<comments>http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 15:38:26 +0000</pubDate>
		<dc:creator>Andrej Bauer</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://math.andrej.com/?p=184</guid>
		<description><![CDATA[I quite like Python for teaching. And people praise it for the lambda construct which is a bit like λ-abstraction in functional languages. However, it is broken!
To see how lambda is broken, try generating a list of functions `fs = [f_0, ..., f_9]` where `f_i(n) = i + n`. First attempt:

&#62;&#62;&#62; fs = [(lambda n: [...]]]></description>
			<content:encoded><![CDATA[<p>I quite like Python for teaching. And people praise it for the <code>lambda</code> construct which is a bit like λ-abstraction in functional languages. However, it is <strong>broken</strong>!</p>
<p><span id="more-184"></span>To see how <code>lambda</code> is broken, try generating a list of functions `fs = [f_0, ..., f_9]` where `f_i(n) = i + n`. First attempt:</p>
<blockquote>
<pre>&gt;&gt;&gt; fs = [(lambda n: i + n) for i in range(10)]
&gt;&gt;&gt; fs[3](4)
13</pre>
</blockquote>
<p>Wait a minute, <code>fs[3](4)</code> ought to be <code>3 + 4 = 7</code>! It looks like all 10 functions share the same &#8220;last&#8221; value of <code>i</code>, which is <code>9</code>. Indeed:</p>
<blockquote>
<pre>&gt;&gt;&gt; [f(4) for f in fs]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]</pre>
</blockquote>
<p>This is certainly unexpected. Let us try to get around the problem by not using <code>lambda</code>:</p>
<blockquote>
<pre>&gt;&gt;&gt; fs = []
&gt;&gt;&gt; for i in range(10):
...    def f(n): return i+n
...    fs.append(f)
...
&gt;&gt;&gt; [f(4) for f in fs]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]</pre>
</blockquote>
<p>Still not working, so the reason is deeper, probably in the way environments are handled. Maybe like this:</p>
<blockquote>
<pre>&gt;&gt;&gt; fs = []
&gt;&gt;&gt; for i in range(10):
...    def f(n, i=i): return i+n
...    fs.append(f)
...
&gt;&gt;&gt; [f(4) for f in fs]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]</pre>
</blockquote>
<p>Victory! But try explaining to students what is going on.</p>
<p>Just to be sure, Haskell does the right thing, of course!</p>
<blockquote>
<pre>Prelude&gt; let fs = [(\n -&gt; i + n) | i &lt;- [0..9]]
Prelude&gt; [f(4) | f &lt;- fs]
[4,5,6,7,8,9,10,11,12,13]</pre>
</blockquote>
<p>What were the implementors of Python thinking?!</p>
]]></content:encoded>
			<wfw:commentRss>http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/feed/</wfw:commentRss>
		</item>
		<item>
		<title>How to simulate booleans in simply typed lambda calculus?</title>
		<link>http://math.andrej.com/2009/03/21/how-to-simulate-booleans-in-simply-typed-lambda-calculus/</link>
		<comments>http://math.andrej.com/2009/03/21/how-to-simulate-booleans-in-simply-typed-lambda-calculus/#comments</comments>
		<pubDate>Sat, 21 Mar 2009 09:22:36 +0000</pubDate>
		<dc:creator>Andrej Bauer</dc:creator>
		
		<category><![CDATA[Computation]]></category>

		<guid isPermaLink="false">http://math.andrej.com/?p=168</guid>
		<description><![CDATA[I have been writing lecture notes on computable mathematics. One of the questions that came up was whether it is possible to simulate the booleans in the simply-typed λ-calculus. This is a nice puzzle in functional programming. If you solve it, definitely let me know, although I suspect logicians did it a long time ago.
The [...]]]></description>
			<content:encoded><![CDATA[<p>I have been writing lecture notes on computable mathematics. One of the questions that came up was whether it is possible to simulate the booleans in the <a href="http://en.wikipedia.org/wiki/Simply_typed_lambda_calculus">simply-typed λ-calculus</a>. This is a nice puzzle in functional programming. If you solve it, definitely let me know, although I suspect logicians did it a long time ago.</p>
<p>The simply-typed λ-calculus is a purely functional language in which we have a single base type, functions, and pairs. In this language every term normalizes, so we cannot write a non-terminating program, and it does not matter whether we evaluate eagerly or lazily. To make things more concrete, let me rephrase this as a fragment of Haskell (Ocaml or ML would do just as well). We may use <em>only the following constructs</em>:</p>
<ol>
<li>An abstract &#8220;base&#8221; type, which is traditionally denoted by <em>O</em> (the letter). In Ocaml this would be a type whose implementation is hidden by a signature. I am not quite sure what it is in Haskell, but it could be a type parameter about which nothing is known. For practical purposes we may take <em>O</em> to be <em>Int</em> and make sure we do not use anything specific about <em>Int</em>.</li>
<li>Functions: we may form functions by λ-abstraction and apply them. Very importantly, <em>all variables must be explicitly typed (polymorphism is forbidden).</em> For example, it is ok to write <code>\(x :: O) -&gt; x</code> but not <code>\x -&gt; x</code> because that would be polymorphic. (We must include the pragma <code>{-# LANGUAGE PatternSignatures #-}</code> in Haskell code to allow explicitly typed variables.)</li>
<li>Pairs: we may form pairs and use the projections <code>fst</code> and <code>snd</code>. This is really just a convenience, because we can always elimitate pairs by currying.</li>
</ol>
<p>The question is this: is there a type <em>Boolean</em> (constructed from the base type <em>O</em> using function types and product types) with values</p>
<blockquote>
<pre>true   :: Boolean
false  :: Boolean</pre>
</blockquote>
<p>and for each type <code>t</code> a constant</p>
<blockquote>
<pre>cond_t :: Boolean -&gt; t -&gt; t -&gt; t</pre>
</blockquote>
<p>such that, for all <code>x</code> and <code>y</code> of type <code>t</code>:</p>
<blockquote>
<pre>cond_t true  x y = x
cond_t false x y = y</pre>
</blockquote>
<p>Notice that since polymorphism is forbidden, we have a family of constants <code>cond_t</code>, one for each type <code>t</code>, that simulate the conditional statement.</p>
<h4>Booleans via polymorphism</h4>
<p>If we allow polymorphic functions, the booleans may be defined thus:</p>
<blockquote>
<pre>type Boolean t = t -&gt; t -&gt; t

true, false :: Boolean t
true  x y = x
false x y = y

cond :: Boolean t -&gt; t -&gt; t -&gt; t
cond  b x y = b x y</pre>
</blockquote>
<p>Of course, since we have polymorphism a single <code>cond</code> does the job.</p>
<p>I suspect the answer is negative and the booleans cannot be simulated.</p>
]]></content:encoded>
			<wfw:commentRss>http://math.andrej.com/2009/03/21/how-to-simulate-booleans-in-simply-typed-lambda-calculus/feed/</wfw:commentRss>
		</item>
		<item>
		<title>On the Failure of Fixed-point Theorems for Chain-complete Lattices in the Effective Topos</title>
		<link>http://math.andrej.com/2009/01/23/on-the-failure-of-fixed-point-theorems-for-chain-complete-lattices-in-the-effective-topos/</link>
		<comments>http://math.andrej.com/2009/01/23/on-the-failure-of-fixed-point-theorems-for-chain-complete-lattices-in-the-effective-topos/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 15:17:07 +0000</pubDate>
		<dc:creator>Andrej Bauer</dc:creator>
		
		<category><![CDATA[Constructive math]]></category>

		<category><![CDATA[Publications]]></category>

		<guid isPermaLink="false">http://math.andrej.com/?p=159</guid>
		<description><![CDATA[Abstract: In the effective topos there exists a chain-complete distributive lattice with a monotone and progressive endomap which does not have a fixed point. Consequently, the Bourbaki-Witt theorem and Tarski’s fixed-point theorem for chain-complete lattices do not have constructive (topos-valid) proofs.
Download: fixed-points.pdf
]]></description>
			<content:encoded><![CDATA[<p><strong>Abstract:</strong> In the effective topos there exists a chain-complete distributive lattice with a monotone and progressive endomap which does not have a fixed point. Consequently, the Bourbaki-Witt theorem and Tarski’s fixed-point theorem for chain-complete lattices do not have constructive (topos-valid) proofs.</p>
<p><strong>Download:</strong> <a href="http://math.andrej.com/wp-content/uploads/2009/01/fixed-points.pdf">fixed-points.pdf</a></p>
]]></content:encoded>
			<wfw:commentRss>http://math.andrej.com/2009/01/23/on-the-failure-of-fixed-point-theorems-for-chain-complete-lattices-in-the-effective-topos/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
