<?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-26662278</id><updated>2011-12-18T13:19:52.728-08:00</updated><category term='qi'/><title type='text'>Programming Kung Fu Qi</title><subtitle type='html'>Learning Qi... one type at a time.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-26662278.post-3849980930003276288</id><published>2007-08-23T09:27:00.000-07:00</published><updated>2007-09-13T20:38:18.408-07:00</updated><title type='text'>Existential Data Constructors in Haskell and Qi</title><content type='html'>In Haskell, if we have a type A and a set of functions from A to some other type, we may wish to encapsulate this logic inside of a new general type that does not contain a reference to A. We would like to be able to pass different data and functions to this type constructor and have the dependent functions work across all types, given a proper datatype for our function and data that matches that datatype. Haskell calls this pattern "Existential Data Construction."&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://research.microsoft.com/%7Esimonpj/papers/history-of-haskell/history.pdf"&gt;A History of Haskell: Being Lazy With Class &lt;/a&gt;, Hudak, Hughes, Wadler, and Jones provide the following Haskell datatype as motivation for existential data constructors.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;data T = forall a. MkT a (a-&gt;Int)&lt;br /&gt;f :: T -&gt; Int&lt;br /&gt;f (MkT x g) = g x&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Reading this type is fairly straight forward. We say that for any type &lt;span style="font-style: italic;"&gt;a&lt;/span&gt;, we can call a constructor consisting of a value of that type and a function from type &lt;span style="font-style: italic;"&gt;a -&gt; Int&lt;/span&gt; and get a type &lt;span style="font-style: italic;"&gt;T&lt;/span&gt; back. F then takes this supplied &lt;span style="font-style: italic;"&gt;T&lt;/span&gt; value and uses pattern matching to deconstruct it and forces the call of G on X. Given that G is of type &lt;span style="font-style: italic;"&gt;(a-&gt;Int)&lt;/span&gt; and X is of type &lt;i&gt;a&lt;/i&gt;, we can be certain this call will work.&lt;br /&gt;&lt;br /&gt;I'm belaboring this point because I think it is important to understand that the Qi type system has this expressive power without requiring a &lt;span style="font-style: italic;"&gt;(forall a)&lt;/span&gt; existential constructor in the type. In Qi, we can simply specify some generic type A on the right hand side of the type colon around a variable bound below the sequent refinement rule and rest assured that the type theory will deduce the existence of and proper type for A at compile time.&lt;br /&gt;&lt;br /&gt;Here is how T looks inside of Qi.&lt;br /&gt;&lt;pre&gt;(datatype t&lt;br /&gt;X : A;&lt;br /&gt;L : (A --&gt; number);&lt;br /&gt;======&lt;br /&gt;(@p mk_t (@p X L)) : t;&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We can read this as saying, "If I need to prove something is of type t I must first prove that it is a constructor that has an X of some arbitrary type A and a function L of type A --&gt; number."&lt;br /&gt;&lt;br /&gt;From there, we can define the function f in a similar manner as the Haskell code.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define f&lt;br /&gt;{ t --&gt; number }&lt;br /&gt;(@p mk_t (@p X G)) -&gt; (G X))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Running this shows how the type system ensures that the A's match up inside the constructor.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(3+) (f (@p mk_t (@p 3 (+ 4))))&lt;br /&gt;7 : number&lt;br /&gt;&lt;br /&gt;(4+) (f (@p mk_t (@p a (+ 4))))&lt;br /&gt;error: type error&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Like in Haskell, this existential datatype constructor truly covers all types A, as I will show below. In the following code, the type A is bound to (number --&gt; number). Qi, like Haskell, really means it when it says, "any type A".&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(7+) (/. X (+ X 3))&lt;br /&gt;#function :LAMBDA [X] [+ X 3] : (number --&gt; number)&lt;br /&gt;&lt;br /&gt;(8+) (f (@p mk_t (@p   (/. X (+ X 3))&lt;br /&gt;                     (/. Y   (Y 7))   ))   )&lt;br /&gt;10 : number&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I hope this explanation helps further the understanding of the Qi type system for Haskell users interested in Qi. Feel free to ask any questions you may have.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-3849980930003276288?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/3849980930003276288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=3849980930003276288' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/3849980930003276288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/3849980930003276288'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/08/existential-data-constructors-in.html' title='Existential Data Constructors in Haskell and Qi'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-8501438147440503338</id><published>2007-08-17T10:58:00.000-07:00</published><updated>2007-08-23T09:27:10.686-07:00</updated><title type='text'>Haskell-like Type Classes in Qi</title><content type='html'>In my studies of Qi, I often use Haskell as an endless pool for mining good ideas. I find that by translating these ideas into Qi, I end up learning both Qi and Haskell better than I would have done by trying to understand them separately. For example, I was immediately able to understand that "Multi-parameter Type Classes with Undecidable instances" was really just "Sequents with bad syntax." But one area that Haskell reigns supreme is the Type Class.&lt;br /&gt;&lt;br /&gt;Qi does have a sub-classing mechanism. If you define a type under the universal truth that &lt;code&gt; (subtype integer number) &lt;/code&gt; then you can define a type rule that says &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;      (subtype B A); X : B;&lt;br /&gt;      _____________________&lt;br /&gt;&lt;br /&gt;      X : A;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and integers can now go wherever numbers go. Basically, it is a promise to the compiler that you are REALLY sure the implementations of the types match up and all the proper functions have been provided. Honest. You promise... That tends to fail in practice. And this sub-classing system does not provide any ability to do ad hoc polymorphism.&lt;br /&gt;&lt;br /&gt;The Haskell idea is to use special syntax to pass around a hidden object that carries all of the required functions and is properly typed. They call this a Type Class. It is an incredibly handy feature because it provides a way to guarantee that you have met the basic needs of a function that requires the type class. It also allows function overloading, a feature Qi lacks.&lt;br /&gt;&lt;br /&gt;So how would this feature look if ported inside of Qi? I would imagine it would looks something like the following code snippet. Note that the "class_" prefix on * is due to Qi not allowing the redefinition of operators. I'll use that notation convention throughout, as I rebuild the (num N) class in Qi.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define square&lt;br /&gt;  { (num N) ==&gt; N --&gt; N }&lt;br /&gt;  X -&gt; (class_* X X))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The meaning of the statement is the same as Haskell. If I have a (num N) class then I can use the class_* to call the proper function. Internally, Qi would transform this construct into the following along the same manner as Haskell.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define square&lt;br /&gt;  { (num N) --&gt; N --&gt; N }&lt;br /&gt;  D X -&gt; (num_* D X X))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The code to perform this transformation will not be provided. This code would have to be intimately tied into the type system and would require a very large change to Qi. It may be worth it, but it is not the point of this article. I will perform the transformation by hand and demonstrate from there.&lt;br /&gt;&lt;br /&gt;For the purposes of this article, I will be providing the base types integer and float. They both have their own type specific operations. I will create instances of them into the (num N) class which will also propagate that instance to the subtype (eq N).&lt;br /&gt;&lt;br /&gt;Haskell defines the EQ class as&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class  Eq a  where&lt;br /&gt;    (==), (/=)       :: a -&gt; a -&gt; Bool&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Haskell hides the creation of the constructor type for EQ, but in the final transformation it gets an explicit expression inside the compiler.  The final transformation should create both a new Qi datatype and some new generic functions that the type class requires. I provide the transformation in Qi below.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(datatype eq&lt;br /&gt;  Equal    : (A --&gt; (A --&gt; boolean));&lt;br /&gt;  NotEqual : (A --&gt; (A --&gt; boolean));&lt;br /&gt;  ===&lt;br /&gt;  (@p mkeq (@p Equal NotEqual)) : (eq A);&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(define class_equal&lt;br /&gt;  { (eq N) --&gt; N --&gt; N --&gt; boolean }&lt;br /&gt;  (@p mkeq  (@p Equal _))  &lt;br /&gt;  X Y -&gt; (Equal X Y))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define class_notequal&lt;br /&gt;  { (eq N) --&gt; N --&gt; N --&gt; boolean }&lt;br /&gt;  (@p mkeq  (@p _ NotEqual))&lt;br /&gt;  X Y -&gt; (NotEqual X Y))&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the idea is to pass along the proper EQ object for the function type and use pattern matching to splice in the arguments and the proper function and then call it. Getting this transformation to take arbitrary code and make these datatypes and functions requires most of the work. The final result can work as these hand written functions do, but a real implementation would structure things differently.&lt;br /&gt;&lt;br /&gt;The instance declaration in Haskell looks something like the following&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;instance Eq Integer where &lt;br /&gt;  x == y                =  x `integerEq` y&lt;br /&gt;&lt;br /&gt;instance Eq Float where&lt;br /&gt;  x == y                =  x `floatEq` y&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The final transformation of the Qi code would look like the following snippet. It provides the needed functions for the type class by taking the type specific functions and putting them into a type class container. This is the same container that we send to every function that requires a type class. All we need to do is provide the base implementations in the proper spots. In a full Qi type class implementation, we would have to use some special syntax or data structure to cause these functions to auto-generate themselves. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define instance-eq-integer&lt;br /&gt;  { A --&gt; (eq integer) }&lt;br /&gt;  _ -&gt; (@p mkeq  (@p equal-integer notequal-integer)))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define instance-eq-float&lt;br /&gt;  { A --&gt; (eq float) }&lt;br /&gt;  _ -&gt; (@p mkeq  (@p equal-float notequal-float)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When we run the code, it behaves as expected.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(39+) (class_equal (instance-eq-float 0) 2.3 2.3)&lt;br /&gt;true : boolean&lt;br /&gt;&lt;br /&gt;(40+) (class_equal (instance-eq-float 0) 2.3 2.4)&lt;br /&gt;false : boolean&lt;br /&gt;&lt;br /&gt;(41+) (class_equal (instance-eq-integer 0) 2 2)&lt;br /&gt;true : boolean&lt;br /&gt;&lt;br /&gt;(42+) (class_equal (instance-eq-float 0) 2.0 2)&lt;br /&gt;error: type error&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that line 42 fails. To perform this kind of analysis, we will need a type class that captures both equality and the idea of being a number, with a way to translate them from the integers. Haskell defines the (num N) type in a way very close to the form below.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class  (Eq a) =&gt; Num a  where&lt;br /&gt;    (+), (-), (*)    :: a -&gt; a -&gt; a&lt;br /&gt;    negate           :: a -&gt; a&lt;br /&gt;    abs, signum      :: a -&gt; a&lt;br /&gt;    fromInteger      :: Integer -&gt; a&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can define an equivalent structure in Qi by embedding the eq subclass directly into the mknum structure. The compiler would also need to provide a function to walk the subclass tree.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(datatype num&lt;br /&gt;  Subclass : (eq A);&lt;br /&gt;  Plus   : (A --&gt; (A --&gt; A));&lt;br /&gt;  Minus  : (A --&gt; (A --&gt; A));&lt;br /&gt;  Mult   : (A --&gt; (A --&gt; A));&lt;br /&gt;  Neg    : (A --&gt; A);&lt;br /&gt;  Abs    : (A --&gt; A);&lt;br /&gt;  SigNum : (A --&gt; A);&lt;br /&gt;  FromInteger : (integer --&gt; A);&lt;br /&gt;  ===&lt;br /&gt;  (@p&lt;br /&gt;  Subclass&lt;br /&gt;  (@p mknum (@p Plus &lt;br /&gt;            (@p Minus&lt;br /&gt;            (@p Mult&lt;br /&gt;            (@p Neg&lt;br /&gt;            (@p Abs&lt;br /&gt;            (@p SigNum FromInteger)))))))) : (num A);&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(define num_to_eq&lt;br /&gt;  {(num N) --&gt; (eq N)}&lt;br /&gt;  (@p&lt;br /&gt;  (@p mkeq  (@p E Ne))&lt;br /&gt;  (@p mknum (@p _&lt;br /&gt;          (@p _&lt;br /&gt;          (@p _&lt;br /&gt;          (@p _&lt;br /&gt;   (@p _&lt;br /&gt;   (@p _ _)))))))) -&gt; (@p mkeq  (@p E Ne)))&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The basic function definitions work like equal type class from above.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define class_*&lt;br /&gt;  { (num N) --&gt; N --&gt;  N --&gt; N  }&lt;br /&gt;  (@p&lt;br /&gt;  _&lt;br /&gt;  (@p mknum (@p Plus &lt;br /&gt;          (@p Minus&lt;br /&gt;          (@p Mult&lt;br /&gt;          (@p Neg&lt;br /&gt;   (@p Abs&lt;br /&gt;   (@p SigNum FromInteger))))))))&lt;br /&gt;&lt;br /&gt;  X Y -&gt; (Mult X Y))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And we declare the instance by providing all of the functions in their proper slots.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define instance-num-integer&lt;br /&gt;  { A --&gt; (num integer) }&lt;br /&gt;  _ -&gt; &lt;br /&gt;  (@p&lt;br /&gt;  (instance-eq-integer 0)&lt;br /&gt;  (@p mknum (@p plus-integer &lt;br /&gt;          (@p minus-integer&lt;br /&gt;          (@p mult-integer&lt;br /&gt;          (@p neg-integer&lt;br /&gt;   (@p abs-integer&lt;br /&gt;   (@p signum-integer frominteger-integer)))))))) )&lt;br /&gt;&lt;br /&gt;(define instance-num-float&lt;br /&gt;  { A --&gt; (num float) }&lt;br /&gt;  _ -&gt; &lt;br /&gt;  (@p&lt;br /&gt;  (instance-eq-float 0)&lt;br /&gt;  (@p mknum (@p plus-float &lt;br /&gt;          (@p minus-float&lt;br /&gt;          (@p mult-float&lt;br /&gt;          (@p neg-float&lt;br /&gt;   (@p abs-float&lt;br /&gt;   (@p signum-float frominteger-float)))))))) )&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So now we have what we need to take on 2.0 == 2.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(class_equal (num_to_eq (instance-num-float 0)) &lt;br /&gt;             2.0 &lt;br /&gt;             (class_frominteger (instance-num-float 0) 2))&lt;br /&gt;true : boolean&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If we encapsulate that into a function 'istwo?' we can see the transformation a bit more clearly.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define istwo?&lt;br /&gt;  { (num N) --&gt; N --&gt; boolean }&lt;br /&gt;  D X -&gt; (class_equal (num_to_eq D) (class_frominteger D 2) X))&lt;br /&gt;&lt;br /&gt;istwo? : ((num A) --&gt; (A --&gt; boolean))&lt;br /&gt;&lt;br /&gt;(10+) (istwo? (instance-num-integer 0) 2)&lt;br /&gt;true : boolean&lt;br /&gt;&lt;br /&gt;(11+) (istwo? (instance-num-integer 0) 3)&lt;br /&gt;false : boolean&lt;br /&gt;&lt;br /&gt;(12+) (istwo? (instance-num-float 0) 2.0)&lt;br /&gt;true : boolean&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ideally, the above 'istwo?' function should be auto-generated by the following Qi like code. Note that the type system would wrap the small constants in frominteger and call the subclass datatype return function to make a valid class_equal call.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define istwo?&lt;br /&gt;  { (num N) ==&gt; N --&gt; boolean }&lt;br /&gt;  X -&gt; (class_equal 2 X))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To finish, I'll implement squares and sumsquares that work across the type class (num N).&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define square&lt;br /&gt;  { (num N) --&gt; N --&gt; N }&lt;br /&gt;  D X -&gt; (class_* D X X))&lt;br /&gt;&lt;br /&gt;(define sumsquares&lt;br /&gt;  { (num N) --&gt; N --&gt; N }&lt;br /&gt;  D X -&gt; (class_+ D (square D X)&lt;br /&gt;                    (square D X)))&lt;br /&gt;&lt;br /&gt;(16+) (square (instance-num-float 0) 6.0)&lt;br /&gt;36.0 : float&lt;br /&gt;&lt;br /&gt;(17+) (square (instance-num-integer 0) 2)&lt;br /&gt;4 : integer&lt;br /&gt;&lt;br /&gt;(18+) (sumsquares (instance-num-integer 0) 2)&lt;br /&gt;8 : integer&lt;br /&gt;&lt;br /&gt;(19+) (sumsquares (instance-num-float 0) 6.0)&lt;br /&gt;72.0 : float&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In short, type classes are a very powerful programming tool that Qi lacks and should probably have. They give Qi ad hoc polymorphism and define types that also have guarantees about which functions it supports. It would take a fairly large change to the Qi codebase to support the shorthand syntax, but I hope this article has proven that we can implement the powerful Haskell type system in Qi. &lt;br /&gt;&lt;br /&gt;Thank you for your time.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://qilang.googlecode.com/files/type_class.qi"&gt; Download the full code used to make this article. &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-8501438147440503338?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/8501438147440503338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=8501438147440503338' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/8501438147440503338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/8501438147440503338'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/08/haskell-like-type-classes-in-qi.html' title='Haskell-like Type Classes in Qi'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-7348066037804614031</id><published>2007-07-17T20:56:00.000-07:00</published><updated>2007-07-17T21:00:00.271-07:00</updated><title type='text'>Qi 9 Win32 Installer</title><content type='html'>&lt;h3&gt; Just a note: &lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;You can get the new version of Qi at the &lt;a href="http://code.google.com/p/qilang/"&gt; Google Qi page.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can also download the &lt;a href="http://qilang.googlecode.com/files/InstallQi.exe"&gt; Win32 Installer.&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-7348066037804614031?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/7348066037804614031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=7348066037804614031' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/7348066037804614031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/7348066037804614031'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/07/qi-9-win32-installer.html' title='Qi 9 Win32 Installer'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-4486761185217087314</id><published>2007-06-02T01:42:00.000-07:00</published><updated>2007-06-06T04:14:14.996-07:00</updated><title type='text'>A Simple SK Combinator Calculus Tutorial in Qi</title><content type='html'>As a juxtaposition of my previous use of the Qi type checker to define the SK combinator calculus, I'll now define it very simply in the Qi language directly. I'll present this as a tutorial to those new to the &lt;a href="http://en.wikipedia.org/wiki/SKI_combinator_calculus"&gt;SK combinator calculus.&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The SK calculus shows us that at maximum there are only three rules of logic: Pattern Matching, Deleting, and Copying. It also shows that their is only one way of evaluating them, namely by application. You can think of the three rules as "Highlighting", "Cutting", and "Pasting." With those three simple operations, the entirety of logic and mathematics can be reproduced with only your mouse!&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Let us take a loot at deletion... We'll call the operation K.  Look at the following transformation. Copy the [[kx]y] into a text editor. Now highlight and "cut" all but the x using only  the "cut" command and your mouse.&lt;pre&gt;[[kx]y] -&gt; x&lt;/pre&gt;&lt;br /&gt;Now, we'll make a new function S which stands for "paste". Try to make the following transformation of [[[sx]y]z] in a text editor. Remember you can only use "cut" and "paste".&lt;pre&gt;[[[sx]y]z] -&gt; [[xz][yz]]&lt;/pre&gt;K deletes information and S copies things and applies it to other functions.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Now it should be very easy to understand what the first two lines of following code is doing.&lt;pre&gt;(define sk-eval*&lt;br /&gt;&lt;br /&gt;[[k X] Y] -&gt; X&lt;br /&gt;[[[s F] G] X] -&gt; [[F X] [G X]]&lt;br /&gt;&lt;br /&gt;[ X Y] -&gt; [(sk-eval X) (sk-eval Y)] &lt;br /&gt;X -&gt; X)&lt;/pre&gt;The last 2 lines simply tell the function to evaluate the inside of our 2 element lists and return anything it doesn't know how to handle.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;But you should notice that we have defined sk-eval* but not sk-eval, so we are not quite done yet. What do we mean by evaluation? We should mean that every element has been reduced and modified until we get the same thing back out of our evaluation function as we put into it. In math, an x for a function f with the properties f(x)=x is known as a &lt;a href="http://mathworld.wolfram.com/MapFixedPoint.html"&gt; fixed point. &lt;/a&gt; It simply means that we get the same input as output. You should notice that "X -&gt; X" in the sk-eval* function (especially being last), makes this a case where we get to use the &lt;b&gt;fix&lt;/b&gt; built-in function in Qi. It keeps applying the function to itself until it reaches a fixpoint. Then it stops.&lt;pre&gt;(define sk-eval&lt;br /&gt;X -&gt; (fix sk-eval* X))&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's it! That's all it takes to complete the evaluator. In our cut and paste metaphor, we would continue to make the required copy and pastes until we could no longer match s and k's with the rules defined above.&lt;br /&gt;&lt;br /&gt;Now let us see it in action.&lt;pre&gt;(36-) (sk-eval [[[s k] k] a])&lt;br /&gt;a&lt;br /&gt;(37-) (sk-eval [[[s [[s k] k]] [[s k] k]] a])&lt;br /&gt;[a a]&lt;/pre&gt;&lt;br /&gt;That's pretty easy. Now let us define some helper functions and show that this sk-eval function knows math.&lt;pre&gt;(define sk    -&gt; [s k])&lt;br /&gt;(define kk    -&gt; [k k])&lt;br /&gt;(define ks    -&gt; [k s])&lt;br /&gt;(define z     -&gt; (sk))&lt;br /&gt;(define succ  -&gt;  [ s [ [ s (ks)] k]])&lt;br /&gt;(define plus  -&gt;  [ [ s (ks)] [ [ s [ k [ s [ k s]]]]&lt;br /&gt;     [ s (kk)]]])&lt;br /&gt;(define mult  -&gt;  [ [ s (ks)] k])&lt;br /&gt;(define one   -&gt;  [ (succ) (z)])&lt;br /&gt;(define two   -&gt;  [ (succ) (one)])&lt;br /&gt;(define three -&gt;  [ (succ) (two)])&lt;br /&gt;(define four  -&gt;  [ (succ) (three)] )&lt;br /&gt;(define five  -&gt;  [ (succ) (four)] )&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And now it is time for it to do some math. We will use 1 and 0 to as markers for our functional application to ensure that our evaluator will output a string of the answer in 1's but ended by a 0. &lt;pre&gt;(40-) (sk-eval [[[[(plus) (one)] (two)] 1] 0])&lt;br /&gt;[1 [1 [1 0]]]&lt;br /&gt;(41-) (sk-eval [[[[(mult) (three)] (two)] 1] 0])&lt;br /&gt;[1 [1 [1 [1 [1 [1 0]]]]]]&lt;br /&gt;&lt;/pre&gt;You could easily host an named SK calculus with the addition of 2 lines of code. I'll leave that as an exercise to the reader. &lt;br /&gt;&lt;p&gt;&lt;br /&gt;That's all there is to the SK Combinator Calculus. It is a powerful enough system to define the entirety of mathematics and computation. It shows that all you need is a basic way to match symbols, delete symbols, and copy symbols and you have a Turing Complete system. (I know some squishy bio-computers that do this all the time and perhaps I'll explore that idea in another post.) From this very basic system, you get the entirety of reasoned knowledge. The universe is a strange place indeed.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I hope this helped spread understanding about the SK combinator calculus. Let me know of any questions you have!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-4486761185217087314?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/4486761185217087314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=4486761185217087314' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/4486761185217087314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/4486761185217087314'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/06/simple-sk-combinator-calculus-tutorial.html' title='A Simple SK Combinator Calculus Tutorial in Qi'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-4068096490813424709</id><published>2007-05-26T22:02:00.000-07:00</published><updated>2007-11-29T00:15:39.433-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='qi'/><title type='text'>A SK Combinator in the Qi Type System, a Comparison with Haskell</title><content type='html'>&lt;pre&gt;\&lt;/pre&gt;Today I present another proof of the Turing completeness of the Qi type system. I have derived the code for this article from an article about Turing complete Haskell types named &lt;a href="http://article.gmane.org/gmane.comp.lang.haskell.general/14088"&gt;The GHC typechecker is Turing-complete&lt;/a&gt; by Robert Dockins. In keeping with the tradition of his article, this message is also in a compilable form as long as you grab the starting and ending comment markers. Qi could use a literate code mode.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The &lt;a href="http://en.wikipedia.org/wiki/SKI_combinator_calculus"&gt; SKI combinator calculus&lt;/a&gt; is a computation system reduced to its most minimal form. There are exactly 2 operators, S and K. S applies its first two arguments to the third argument while K deletes the second of its two arguments. From that simple strategy, all the known computable functions can be derived. This article will show how this is done in Qi.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;I have taken the approach of directly translating, as much as possible, the Haskell article's code into Qi. This should assure you that the same computations are going on and perhaps better convince you of the complete mapping of the SK calculus to Qi types. I will not be providing a correctness proof here.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Firstly, we define empty types that resolve to the primitives s, k, and the pairing operation app. I also define a dummy type (other A) that will allow us to test the application of arbitrary subexpressions that we can conveniently label. Notice that these definitions all type to any variable. I label this variable Bot in the program to indicate that we do not really care about its actual type, we are just using it to host a typechecking operation in the same way as the Haskell program. Either the program will typecheck indicating a successfully application or it will return a type error. We takes these values as true and false respectively.&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;\&lt;br /&gt;(datatype sk&lt;br /&gt;___&lt;br /&gt;Bot : s0;&lt;br /&gt;___&lt;br /&gt;Bot : k0;&lt;br /&gt;___&lt;br /&gt;Bot : (app A B);&lt;br /&gt;___&lt;br /&gt;Bot : (other A);&lt;br /&gt;\&lt;/pre&gt; In keeping with the Haskell code, we now define a single step sk reduction named sk_eval. The evaluator will always reduce the leftmost-outer redix. It will always be  &lt;a href="http://en.wikipedia.org/wiki/Reflexive_relation"&gt; reflexive &lt;/a&gt; on normal forms. I then create a transitive closure over a sk_eval reduction. I have named the type that does this sk_run.&lt;br /&gt;&lt;br /&gt;I will define a combination type to reduce some of the more expensive operations in parallel. If we have an ((S x) y) we know that we will have to reduce both x and y. When we are done reducing x and y, we will need a type to tell the typechecker that we have finished these operations. The following code defines the combine_done type that takes the status of 2 operations and returns done if they both are done.&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;___&lt;br /&gt;Bot : (combine_done done done done);&lt;br /&gt;___&lt;br /&gt;Bot : (combine_done done more more);&lt;br /&gt;___&lt;br /&gt;Bot : (combine_done more done more);&lt;br /&gt;___&lt;br /&gt;Bot : (combine_done more more more);&lt;br /&gt;\&lt;/pre&gt; Now we add the sk_eval type for the default evaluations. S, K, and (other A) all are done when they are equal to each other.&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;____&lt;br /&gt;Bot : (sk_eval s0 s0 done);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval k0 k0 done);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (other A) (other A) done);&lt;br /&gt;\&lt;/pre&gt; All of the previous rules have derived from nothing. That's why the line above the ___ is blank. The next rules are evaluation strategies for when we get near the bottom of the sk tree. If we have been asked if (K x) is equal to (K y) we must ensure x = y. The same goes for (S x).&lt;br /&gt;&lt;p&gt;&lt;br /&gt;As a general reminder about those who have not learned &lt;a href="http://en.wikipedia.org/wiki/Sequent"&gt; sequent notation &lt;/a&gt; you can consider them as saying IF the top part can be proven, THEN the bottom part is true. However you should remember that the type checker is working backwards from the type that we will provide it. So you can think of the operation in Qi as, "If I have something that fits the pattern at the bottom, then I will try to prove the top."&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;\&lt;br /&gt;Bot : (sk_eval X Xp D);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (app k0 X) (app k0 Xp) D);&lt;br /&gt;&lt;br /&gt;Bot : (sk_eval X Xp D);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (app s0 X) (app s0 Xp) D);&lt;br /&gt;\&lt;/pre&gt; Getting that nice "other" type working gives us some problems. We cannot reduce it any further but we may have to reduce other parts of pairs that are nearby the other type. The one-arity case is very easy.&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;Bot : (sk_eval X Xp D);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (app (other A) X) (app (other A) Xp) D);&lt;br /&gt;\&lt;/pre&gt; However in the 2 case, we will need to ensure that the elements to the right fully reduce. That is to say if we have a question if ((p x) y) = ((p x1) y1) we must fully reduce and prove x = x1 and y = y1. The combine_done type now comes in handy as it allows us to fully reduce and prove this assertion.&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;Bot : (sk_eval X Xp D1);&lt;br /&gt;Bot : (sk_eval Y Yp D2);&lt;br /&gt;Bot : (combine_done D1 D2 D);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (app (app (other A) X) Y)&lt;br /&gt;              (app (app (other A) Xp) Yp) D);&lt;br /&gt;\&lt;/pre&gt; You can read the bottom part as saying that if we are trying to prove some sk evaluation that has an (other A) at the head we must then prove that X = Xp and Y = Yp and that they are all done before moving on. We can now do the 3-arity version of the other type as we know it will have to reduce the first 3 arguments before it can accept them. We also do the same thing for a single s0 here.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;Bot : (sk_eval X Xp D1);&lt;br /&gt;Bot : (sk_eval Y Yp D2);&lt;br /&gt;Bot : (sk_eval Z Zp D3);&lt;br /&gt;Bot : (combine_done D1 D2 D4);&lt;br /&gt;Bot : (combine_done D3 D4 D);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (app (app (app (other A) X) Y) Z )&lt;br /&gt;              (app (app (app (other A) Xp) Yp) Zp) D);&lt;br /&gt;&lt;br /&gt;Bot : (sk_eval X Xp D);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (app s0 X) (app s0 Xp) D);&lt;br /&gt;\&lt;/pre&gt; Now we can define s and k themselves. We have 2 important cases for k. ((K x)y) = x and (((K x) y) z) = (x z)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (app (app k0 X) Y)  X  more);&lt;br /&gt;&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (app (app (app k0 X) Y) Z)  (app X Z) more);&lt;br /&gt;\&lt;/pre&gt;&lt;br /&gt;Now we define s as (((S f) g) x) = ((f x) (g x)).&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (app (app (app s0 F) G) X)&lt;br /&gt;              (app (app F X) (app G X))&lt;br /&gt;              more);&lt;br /&gt;\&lt;/pre&gt;&lt;br /&gt;The final sk_eval rule will prove that ((((p q) x) y) z) = (a z) only when (((p q) x) y) = a. This, along with the other rules above for more simple applications, will reduce the sk combinator on a leftmost-outermost basis.&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;Bot : (sk_eval (app (app (app P Q) X) Y)  A  D);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval (app (app (app (app P Q) X ) Y ) Z)&lt;br /&gt;              (app A Z) D);&lt;br /&gt;\&lt;/pre&gt; Like the Haskell code, I take the transitive closure of sk_eval with an auxiliary type. It insures that it is done when x = x. It also provides transitivity by saying that if we must prove some sk_eval_aux x = z, then we can prove it by proving an sk_eval x = y and an sk_eval_aux y = z.&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval_aux X X done);&lt;br /&gt;&lt;br /&gt;Bot : (sk_eval X Y Q);&lt;br /&gt;Bot : (sk_eval_aux Y Z Q);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_eval_aux X Z more);&lt;br /&gt;\&lt;/pre&gt; Now we can create the sk_run class that runs a query. It must prove that x = y by way of using the sk_eval_aux class.&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;Bot : (sk_eval_aux X Y more);&lt;br /&gt;___&lt;br /&gt;Bot : (sk_run X Y);&lt;br /&gt;&lt;br /&gt;)&lt;br /&gt;\&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we have finished defining the basics. Let's try it out. We will check that SKKb = b. Notice that we typecheck vs any particular data. As none of our types require anything from the value being typed, that means that it will match whenever the type is true, regardless of the actual type of what we are testing!&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(1+) 1 : (sk_run (app (app (app s0 k0) k0) (other b)) (other b))&lt;br /&gt;1 : (sk_run (app (app (app s0 k0) k0) (other b)) (other b))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we will turn on the type spier and watch the program reason its way through this type.&lt;br /&gt;&lt;br /&gt;The first step asks the type checker the same question as before. It notices that it is not a default type and poses the type as a goal to the typechecker.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(25+) (spy +)&lt;br /&gt;true : boolean&lt;br /&gt;&lt;br /&gt;(26+) 1 : (sk_run (app (app (app s0 k0) k0) (other b)) (other b))&lt;br /&gt;______________________________________________ 9 inferences&lt;br /&gt;?- 1 : (sk_run (app (app (app s0 k0) k0) (other b)) (other b))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So it finds the sk_eval_aux rule that says if we set x = SKKb and z = b then we can use the transitive rule to evaluate the query. Here we see the firing of that rule as a goal to be proven.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 80 inferences&lt;br /&gt;?- 1 : (sk_eval_aux (app (app (app s0 k0) k0) (other b)) (other b) more)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we will see the sk_eval x y q rule where y has been replaced with the gensym V26232. The type checker now must prove this to continue. This is the point in where it descends out of the transitive closure and does a single evaluation of the input combinator.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 150 inferences&lt;br /&gt;?- 1 : (sk_eval (app (app (app s0 k0) k0) (other b)) V26232 V26233)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Obviously, it will use the s rule in this case to set the y above to be ((Kb)(Kb)). It then sets that to y and we return to the second part of the sk_eval_aux. That part determines if y = z.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 217 inferences&lt;br /&gt;?- 1 : (sk_eval_aux (app (app k0 (other b)) (app k0 (other b))) (other b) more)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now it will try to find some sk_eval such that ((Kb)(Kb)) = y and y = b&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 287 inferences&lt;br /&gt;?- 1 : (sk_eval (app (app k0 (other b)) (app k0 (other b))) V26371 V26372)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;sk_eval will use the k0 rule to return y as (other b). We then return to the second part of the sk_eval_aux and set y = (other b). It will add the second part of that transitive closure rule as a goal.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 352 inferences&lt;br /&gt;?- 1 : (sk_eval_aux (other b) (other b) more)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This will, in turn, set (other b) as an x and ask if there is a y that matches.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 422 inferences&lt;br /&gt;?- 1 : (sk_eval (other b) V26500 V26501)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We know from the very first rules above that the other goal can match (sk_eval (other A) (other A) done) so it sets V26500 as (other b) and V26501 as done.&lt;br /&gt;&lt;br /&gt;Now it only has to ask if (sk_eval_aux (other b) (other b) done) is a finished sk evaluation. The first auxiliary rule says that sk_eval_aux X X done is in fact a true type so it adds the goal, solves it, and finishes.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 480 inferences&lt;br /&gt;?- 1 : (sk_eval_aux (other b) (other b) done)&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;1 : (sk_run (app (app (app s0 k0) k0) (other b)) (other b))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now is SKKb = c?&lt;br /&gt;&lt;pre&gt;(1+) 1 : (sk_run (app (app (app s0 k0) k0) (other b)) (other c))&lt;br /&gt;error: type error &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now let us turn to some of the more complicated combinators. It is here that we find Haskell's type keyword to be more powerful than the Qi alternative "synonym". The Haskell type keyword allows both alias style synonyms like type Z  = SK0 and parametric type synonyms such as type FoldN n = App (App n P) Q. Qi has no way of doing anything similar to parametric type synonyms, so we will be forced to convert the concise definitions in the Haskell code into the full app form inside for Qi.&lt;br /&gt;&lt;br /&gt;I will define a bunch of useful alias synonyms to help us.&lt;br /&gt;&lt;pre&gt;\&lt;br /&gt;(synonyms&lt;br /&gt;&lt;br /&gt; p     (other p0)&lt;br /&gt; q     (other q0)&lt;br /&gt; r     (other r0)&lt;br /&gt;&lt;br /&gt; sk0   (app s0 k0)&lt;br /&gt; skk0  (app (app s0 k0) k0)&lt;br /&gt; sks0  (app (app s0 k0) s0)&lt;br /&gt; ssk0  (app (app s0 s0) k0)&lt;br /&gt; sss0  (app (app s0 s0) s0)&lt;br /&gt; kk0   (app k0 k0)&lt;br /&gt; ks0   (app k0 s0)&lt;br /&gt;&lt;br /&gt; i0    skk0&lt;br /&gt; b0    (app (app s0 ks0) k0)&lt;br /&gt; c0    (app (app s0 (app (app b0 b0) s0)) kk0)&lt;br /&gt; w0    (app c0 (app (app b0 m0) (app (app b0 b0) (app c0 i0))))&lt;br /&gt; l0    (app (app c0 b0) m0)&lt;br /&gt; y0    (app (app s0 l0) l0)&lt;br /&gt; ki0   (app k0 i0)&lt;br /&gt;&lt;br /&gt; m0    (app (app s0 i0) i0)&lt;br /&gt; omega (app m0 m0)&lt;br /&gt;&lt;br /&gt; z       sk0&lt;br /&gt; succ0   (app s0 (app (app s0 ks0) k0))&lt;br /&gt;&lt;br /&gt; plus0   (app (app s0 ks0) (app (app s0 (app k0 (app s0 (app k0 s0))))&lt;br /&gt;    (app s0 kk0)))&lt;br /&gt; mult0   (app (app s0 ks0) k0)&lt;br /&gt; one     (app succ0 z)&lt;br /&gt; two     (app succ0 one)&lt;br /&gt; three   (app succ0 two)&lt;br /&gt; four    (app succ0 three)&lt;br /&gt; five    (app succ0 four)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;\&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When we try out these types, we will find that Qi will fully expand the synonyms and then check the type. It's not pretty to look at, but it works.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(1+) 1 : (sk_run (app succ0 two) three)&lt;br /&gt;1 :&lt;br /&gt;(sk_run&lt;br /&gt;(app (app s0 (app (app s0 (app k0 s0)) k0))&lt;br /&gt; (app (app s0 (app (app s0 (app k0 s0)) k0))&lt;br /&gt;  (app (app s0 (app (app s0 (app k0 s0)) k0)) (app s0 k0))))&lt;br /&gt;(app (app s0 (app (app s0 (app k0 s0)) k0))&lt;br /&gt; (app (app s0 (app (app s0 (app k0 s0)) k0))&lt;br /&gt;  (app (app s0 (app (app s0 (app k0 s0)) k0)) (app s0 k0)))))&lt;br /&gt;&lt;br /&gt;(2+) 1 : (sk_run (app succ0 two) four)&lt;br /&gt;error: type error&lt;br /&gt;&lt;br /&gt;(5+) 1 : (sk_run (app i0 p)  p)&lt;br /&gt;1 : (sk_run (app (app (app s0 k0) k0) (other p0)) (other p0))&lt;br /&gt;&lt;br /&gt;(6+) 1 : (sk_run (app (app (app c0 k0) i0) p) p)&lt;br /&gt;1 :&lt;br /&gt;(sk_run&lt;br /&gt;(app&lt;br /&gt; (app&lt;br /&gt;  (app&lt;br /&gt;   (app&lt;br /&gt;    (app s0&lt;br /&gt;     (app (app (app (app s0 (app k0 s0)) k0) (app (app s0 (app k0 s0)) k0))&lt;br /&gt;      s0))&lt;br /&gt;    (app k0 k0))&lt;br /&gt;   k0)&lt;br /&gt;  (app (app s0 k0) k0))&lt;br /&gt; (other p0))&lt;br /&gt;(other p0))&lt;br /&gt;&lt;br /&gt;(7+) 1 : (sk_run (app (app y0 ki0) p) p)&lt;br /&gt;&lt;br /&gt;(8+) 1 : (sk_run (app m0 p) (app p p))&lt;br /&gt;1 :&lt;br /&gt;(sk_run&lt;br /&gt;(app (app (app s0 (app (app s0 k0) k0)) (app (app s0 k0) k0)) (other p0))&lt;br /&gt;(app (other p0) (other p0)))&lt;br /&gt;&lt;br /&gt;(10+) 1 : (sk_run (app (app (app c0 p) q) r) (app (app p r) q))&lt;br /&gt;(11+) 1 : (sk_run (app (app (app b0 p) q) r) (app p (app q r)))&lt;br /&gt;1 :&lt;br /&gt;(sk_run&lt;br /&gt;(app (app (app (app (app s0 (app k0 s0)) k0) (other p0)) (other q0))&lt;br /&gt; (other r0))&lt;br /&gt;(app (other p0) (app (other q0) (other r0))))&lt;br /&gt;&lt;br /&gt;(12+) 1 : (sk_run omega omega)&lt;br /&gt;*** - Program stack overflow. RESET&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So there you have it, a full SK evaluator inside the Qi type system. I feel that this displayes a lot of evidence for Qi typing being Turing complete, which we already knew. However, I hope that this further shows how much easier it is to reason about the types when using the sequent notation. I find the Qi code much easier to read than the Haskell code. The main area where Haskell shined over Qi is in the parametric type classes. Qi could definately use an extension to the "synonym" keyword. Moreover, Haskell is much better about displaying the type synonyms, leading to less visual junk on the page.&lt;br /&gt;&lt;br /&gt;So for those of you that love Haskell, I hope this shows how Qi types work and their comparable expressive power with Haskell. For those of you who love Qi, hopefully you can now more easily read Haskell multi-parameter type classes. And for Qi implementors, I think it shows some directions for further growth of the Qi language. It's been a long article, thank you for your time and I hope you enjoyed it!&lt;br /&gt;&lt;br /&gt;\&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-4068096490813424709?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/4068096490813424709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=4068096490813424709' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/4068096490813424709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/4068096490813424709'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/05/sk-combinator-in-qi-type-system.html' title='A SK Combinator in the Qi Type System, a Comparison with Haskell'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-5409415221808325757</id><published>2007-05-21T19:28:00.000-07:00</published><updated>2007-05-22T07:19:51.974-07:00</updated><title type='text'>Foldl and Foldr</title><content type='html'>The Haskell prelude defines the types for foldl and foldr as follows.&lt;pre&gt;&lt;br /&gt;foldl&lt;br /&gt;type: foldl :: (a -&gt; b -&gt; a) -&gt; a -&gt; [b] -&gt; a&lt;br /&gt;foldr&lt;br /&gt;type: foldr :: (a -&gt; b -&gt; b) -&gt; b -&gt; [a] -&gt; b&lt;br /&gt;&lt;/pre&gt;In Qi, I have followed that convention in &lt;a href="http://qilang.googlecode.com/svn/trunk/prelude.qi"&gt;the Qi Prelude.&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The reason for defining it this way is fairly easy to see. If we have a binary operator that works over one type and we have an element and a list of that type, then we can use one functions as a drop in replacement for the other. The following code randomly selects foldr or foldl and uses it on a list.&lt;pre&gt;&lt;br /&gt;(47-) ((if (&gt; (random 2) 0) foldr foldl) / 1 [1 2 3])&lt;br /&gt;3/2&lt;br /&gt;(48-) ((if (&gt; (random 2) 0) foldr foldl) / 1 [1 2 3])&lt;br /&gt;1/6&lt;br /&gt;&lt;/pre&gt;But for as how humans tend to think about calling functions, these type orders make reasoning about foldr and foldl more difficult than they need to be. Allow me a few examples to illustrate.&lt;pre&gt;&lt;br /&gt;(26-) (foldl + 1 [ 1 2 3 4 5])&lt;br /&gt;16&lt;br /&gt;(27-) (foldr + 1 [ 1 2 3 4 5])&lt;br /&gt;16&lt;br /&gt;(28-) (foldr * 1 [ 1 2 3 4 5])&lt;br /&gt;120&lt;br /&gt;(29-) (foldl * 1 [ 1 2 3 4 5])&lt;br /&gt;120&lt;br /&gt;(30-) (foldr / 1 [ 1 2 3 4 5])&lt;br /&gt;15/8&lt;br /&gt;(31-) (foldl / 1 [ 1 2 3 4 5])&lt;br /&gt;1/120&lt;br /&gt;(32-) (foldr - 0 [ 1 2 3 4 5])&lt;br /&gt;3&lt;br /&gt;(33-) (foldl - 0 [ 1 2 3 4 5])&lt;br /&gt;-15&lt;br /&gt;&lt;/pre&gt;Obviously there is no difference between foldl and foldr for associative operators. But when we have non-associative operators I think the type order ends up harming readability. I will define a foldr* and foldl* with the type order that feels more natural to me, to display my point. Perhaps this will serve as a useful guide to others who are attempting to understand the difference between foldl and foldr. It should also serve as a reminder that when we try to make one type of programming task easy, we may end up making other reasoning tasks about programs more difficult.&lt;pre&gt;&lt;br /&gt;(define foldl*&lt;br /&gt;  { A --&gt; ( A --&gt; B --&gt; A ) --&gt; [B] --&gt; A }&lt;br /&gt; Z F Ls -&gt; (foldl F Z Ls))&lt;br /&gt;(define foldr*&lt;br /&gt;  { [A] --&gt; ( A --&gt; B --&gt; B ) --&gt; B --&gt; B }&lt;br /&gt; Ls F Z -&gt; (foldr F Z Ls))&lt;br /&gt;&lt;br /&gt;(51-) (foldl* 10 - [1 2 3 4])&lt;br /&gt;0&lt;br /&gt;(52-) (foldr* [1 2 3 4] - 10)&lt;br /&gt;8&lt;br /&gt;&lt;/pre&gt;I think this quite clearly shows that foldl starts from 10 and keeps subtracting to the right while foldr performs the 4 - 10 and moves to the left. In fact, I think that this shows that even the names of foldl and foldr are backwards from the perspective of the neophyte programmer. Nothing about a quick glance at the following gives away the fact that the first operation will be 4 - 10.&lt;pre&gt;&lt;br /&gt;Hugs&gt; foldr (-) 10 [ 1, 2, 3, 4]&lt;br /&gt;8&lt;br /&gt;&lt;/pre&gt;&lt;b&gt; vs.&lt;/b&gt; the re-ordered version, where this is clear.&lt;pre&gt;&lt;br /&gt;(52-) (foldr* [1 2 3 4] - 10)&lt;br /&gt;8&lt;br /&gt;&lt;/pre&gt;I believe that my reordering makes the purpose of foldl and foldr more clear. We can instinctively feel, at a glance, that foldl is taking the list and pushing it left into the first argument by way of the operator. Likewise, we can feel that foldr is "smooshing" the list to the right into the starting value. &lt;br /&gt;&lt;br /&gt;I hope that this helps by giving both a little insight into how making code easier to be drop in replacements for other code can actually hurt readability and by helping people to better understand foldl and foldr. As always, let me know what you think.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-5409415221808325757?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/5409415221808325757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=5409415221808325757' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/5409415221808325757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/5409415221808325757'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/05/foldl-and-foldr.html' title='Foldl and Foldr'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-5022431769465707968</id><published>2007-04-30T10:24:00.000-07:00</published><updated>2007-04-30T10:27:23.110-07:00</updated><title type='text'>Qi 7.2 Win32 Self-Extracting Installer With CLISP bundled</title><content type='html'>Greetings Blogland,&lt;br /&gt;&lt;br /&gt;I have made a quick and dirty one download installer for Qi for the Windows platform. It installs CLISP under the Qi directory and adds a link for Qi in the start menu. I'm using NSIS to create the software so if anyone wants to make the installer better, let me know. I'll be adding the installer code to the SVN repository atthe google code page.&lt;br /&gt;&lt;br /&gt;I've also added a Featured Download on the right hand site to help people get to Qi quicker and easier. This is an easy area that needs more work so if anyone feels like maintaining packages, create them and let me know. I'll keep the Windows package up to date but if anyone wants to take the Linux or OS X side, I'd appreciate it.&lt;br /&gt;&lt;br /&gt;Here is the direct download link&lt;br /&gt;&lt;a href="http://code.google.com/p/qilang/downloads/list"&gt;http://code.google.com/p/qilang/downloads/list&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;but you can easily see it at&lt;br /&gt;&lt;a href="http://code.google.com/p/qilang/"&gt;http://code.google.com/p/qilang/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hopefully this will help spread Qi to new and interesting places. Let me know if you have any problems with the installer, please let me know.&lt;br /&gt;&lt;br /&gt;Until Later...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-5022431769465707968?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/5022431769465707968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/5022431769465707968'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/04/qi-72-win32-self-extracting-installer.html' title='Qi 7.2 Win32 Self-Extracting Installer With CLISP bundled'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-7248979153509521598</id><published>2007-03-21T23:42:00.000-07:00</published><updated>2007-03-22T00:54:10.170-07:00</updated><title type='text'>Tour of Qi 7.2 and 6.2 diff</title><content type='html'>Since my computer is still not back up to speed after my crash (I was making backups during the crash. Praise be the Gods of Irony, I hath mended my ways. Smite me no more!), I thought I'd take a quick tour over the differences between Qi 6.2 and 7.2. So fire up your diff browser and join along on this magical ride in CodeLand! &lt;br /&gt;&lt;br /&gt;And like any good tour, it starts off with a mystery!&lt;br /&gt;&lt;br /&gt;Why on earth is it named Qi 7.2!? I could see going from 6.2 to 7.0 as it now runs on a new Lisp compiler and has some added language features. But I can see no real reason to name it Qi 7.2 other than Mark COULD name it Qi 7.2. Anyway, like any good tour, we now will move on without actually solving the mystery.&lt;br /&gt;&lt;br /&gt;Right away, we find the new definition of "no waffle" for the CMUCL compiler. We also come across a great comment quote: &lt;br /&gt;&lt;br /&gt;\No waffle from the CMU or CLisp compiler.   Speed max, safety min because Qi has a type checker.\&lt;br /&gt;&lt;br /&gt;I like telling the compiler, "Speed Max, Safety Min! because I know better than you!" Of course, Qi has to do a lot of work to "know better" than the compiler, but it's every programmers dream to tell the compiler "full optimization, I've got this nailed!"&lt;br /&gt;&lt;br /&gt;From here, we find some code to handle the different types of closures on CMU, namely the INTERPRETED-FUNCTION type. It almost makes me want to stop and dig into the difference between FUNCTION and EVAL::INTERPRETED-FUNCTION, but this is a tour so we have to get moving.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(DEFUN fix-closures ()&lt;br /&gt;      #+CMU   (SETQ *closures* '(FUNCTION COMPILED-FUNCTION EVAL::INTERPRETED-FUNCTION))&lt;br /&gt;      #+CLISP  (SETQ *closures* '(FUNCTION COMPILED-FUNCTION))&lt;br /&gt;      #-(OR CLISP CMU) (ERROR "Qi does not recognise this platform ~A" (LISP-IMPLEMENTATION-TYPE)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Our next bit of action is when we find the brand new curry rules for tuples. If you have noticed, some of my posts contain monster tuples with so many @p's that your eyes almost bleed. Now Qi will turn (@p name x_loc y_loc) into (@p name (@p x_loc y_loc)) for me! I'm already dreaming of the @p's I get to kill with this feature. We would go hunting for them... but it is a .... we'll YOU know.&lt;br /&gt;&lt;br /&gt;The system function table lets us know that we should expect 2 new system functions, mlet and new-assoc-type. Like a sign in an amusement park, it entices with future happiness. And then, in a moment, it has passed by.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define compile_to_machine_code&lt;br /&gt;  Name Rules -&gt; (do (PUSHNEW Name (value *userdefs*))&lt;br /&gt;                          (compile_to_lisp &lt;br /&gt;                                (put-prop Name lambda (compile_to_lambda &lt;br /&gt;                                      (compile_to_lambda+ Name Rules))))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now we come along and find that compile_to_machine_code stores the name of our function along with a "lambda" property that it keeps the lambda compilation in. It isn't something that you would often think about, but if you end up using property lists with the same name as functions in your code, you would want to know about this.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;\Make association between Qi type and Lisp type.\&lt;br /&gt;(DEFUN new-assoc-type (X Y) (PUSHNEW  (LIST X Y) *assoctypes*) 'associated)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And now we come along to something dangerous and FUN! A play with at your peril type of function. You can now create your own match between a Qi type to a Lisp type. Originally, the assoc list only contained things like numbers, strings, symbols, but now you can add your own. Obviously, use this at your own peril as the typechecker will believe anything you tell it. I believe there may be an article on using that in a pathological manner and seeing what happens. But our boat flows on...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  \Params [F X] -&gt; (lisp_code Params [apply F (lisp_code Params X)])   where (element? F Params) \&lt;br /&gt;&lt;br /&gt;  \Above changed in 7.1\&lt;br /&gt;&lt;br /&gt;  Params [F X] -&gt; [apply F (lisp_code [F | Params] X)]   where (element? F Params)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here we find that the function call now does not recursively lisp_code on the applied function anymore. This won't change the meaning of the code but perhaps it produces faster code on CMU? Perhaps compiling the apply doesn't matter as the params are already taken care of in X? Tour guides often speculate wildly on their subject matter. I choose not to break with that tradition here.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; \Translate mlet into let.    Works for dotted pairs.\&lt;br /&gt;  (define expand-mlet&lt;br /&gt;     [@p W X Y | Z] -&gt; (expand-mlet [@p W [@p X Y | Z]]) &lt;br /&gt;     [mlet V W X Y | Z] -&gt; (expand-mlet [let V W [mlet X Y | Z]])&lt;br /&gt;     [mlet X Y Z] -&gt; (expand-mlet [let X Y Z])&lt;br /&gt;     [X | Y] -&gt; (map-dotted-pair expand-mlet [X | Y])&lt;br /&gt;     X -&gt; X)   &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Yet another gem in 7.2! This will really save on the number of parens in my code. You can now (mlet X 2 Y 3 (+ X Y)) to get 5! The only think I need to implement now is a lambda that does pretty much the same thing. I.e. (/. [ X Y ] (+ X Y)) converts to 2 lambdas in the correct order. You'd think you could do this with a Macro, but you would be wrong. /. is a special form, not to be messed with in any macro. I've tried!&lt;br /&gt;&lt;br /&gt;After some boring CMU details that I'll skip over, we find that the typechecker now calls curry_type in a few more places, presumably to handle the new tuple action, but maybe its just for more complete typing in general. But let us not dally, we are nearly finished! &lt;br /&gt;&lt;br /&gt;And like any good tour, some couple breaks up during it sending us out with a zoom!&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;\Modified in 7.1 to allow stops to be embedded in alphanums.\&lt;br /&gt;\I gave up on Qi-YACC! \&lt;br /&gt;&lt;br /&gt;(define process-prolog-chars&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Apparently, poor Qi Yacc didn't want to parse the input properly. But do not worry, she's still around. And perhaps even she can be cajoled into parsing things correctly with some fancy trickery not yet invented by the human mind. Who knows, it even could be YOOOOUUU!&lt;br /&gt;&lt;br /&gt;Please exit the boat carefully and I hope you have enjoyed this Diff Tour of Qi 6.2 and Qi 7.2. We will return to your irregularly scheduled coding posts after a nice clean OS install.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-7248979153509521598?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/7248979153509521598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=7248979153509521598' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/7248979153509521598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/7248979153509521598'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/03/tour-of-qi-72-and-62-diff.html' title='Tour of Qi 7.2 and 6.2 diff'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-4305328426065118747</id><published>2007-02-26T07:16:00.000-08:00</published><updated>2007-02-26T07:18:19.632-08:00</updated><title type='text'>The Real Reason Why Building Software is not like Building Bridges</title><content type='html'>I have seen many articles expounding on how software is not like bridge building. They attempt to reason about the problem via poorly formed analogies and often miss the actual critical differences between software development and bridge development. You will see things like the number of bolts and rivets compared to the number of lines of code. You will hear about the size of the software problem space vs. the size of the bridge builder's problem space. But none of these articles has ever hit the nail on the head for me, so I thought I would draw an apt analogy that can help both software programmers and bridge engineers understand each other.&lt;br /&gt;&lt;br /&gt;Imagine you are a bridge engineer and have been teleported to an alternate universe to build the Golden Gate Bridge. You have things that look like beams, bolts, and welding torches. You set out to build the bridge and one day your crew finally finishes it. The first traveler gets on the bridge and drives across it, but he winds up in Des Moines, Iowa.&lt;br /&gt;&lt;br /&gt;"What happened?" you exclaim! Your crew laughs at the traveler's predicament. "It must be a bork," they say. One of the crew goes out half way on the bridge, turns a bolt 90 degrees clockwise, and shouts back to send another driver across. Another brave traveler, dubbed "beta-tester" for some reason, sets off across the bridge and finds herself in China. The crew laughs heartily and shouts back, "Give it another spin!" With another 90 degree turn, and another brave traveler later, someone actually drives across the bridge into San Francisco as intended! There is much cheering and the sound of the popping of the Champaign floats across the ocean.&lt;br /&gt;&lt;br /&gt;Just then, you notice a Volvo trying to drive across. You stare in awe at this strange universe wondering if the Volvo ever managed to get across. You tap one of your crew in the back and ask, "Do you think the Volvo will get to the right place?" He drops both his Champaign glass and his jaw. "VOLVO!!!!" he screams! "No, No, NO!" a crew member exclaims. "Didn't you know your world had Volvo's?" you ask. "Of course," he replies, "but we didn't think anyone would be foolish enough to try to drive it across the bridge!"&lt;br /&gt;&lt;br /&gt;Flabbergasted, you wait for the inevitable. Half way across, the poor Volvo starts to float off the ground. It starts to spin over and over again. Horrified, you ask, "Can we make it so we can allow Volvos to drive across after we rescue that poor soul?" "Certainly," comes the reply of the crew chief, "but we'll have to raise the entire bridge by another 4 feet. We could either lift it from the bottom or just put an extra 4 feet of concrete on the surface of the bridge." You choose the latter option, saddened by the fact that your beautiful bridge now has a thick white coat of concrete to accommodate the simple Volvo.&lt;br /&gt;&lt;br /&gt;Thinking your task has finished, you look forward to running far, far away from this universe and back into ours. You then notice 2 cars starting to drive across the bridge in tandem. A familiar feeling of dread fills you as you stammer out, "What happens if the bridge is used in parallel?" "RUN!" comes the screaming reply. No longer questioning the logic of this world, you take off. Looking back, you see a single bolt fall from the top of the bridge. As it falls, it begins to absorb the bridge itself. More and more of the bridge falls INTO the bolt. The cars, bolt, and bridge are lost forever. That is until the crew chief comes over to where the bridge was and pushes a button at the edge of the road. The bridge instantly reappears. He also posts a sign, "No driving on the bridge in parallel."&lt;br /&gt;&lt;br /&gt;Before finally finishing with this world, you turn to ask your crew how this universe works. "It's quite simple," comes the reply. "Any bolt, beam, or other bridge part can be a bridge to any other part of the universe. It is even possible for a part to become a black hole leading to nowhere, as you saw." "Why do you build bridges then?" you ask. "We build bridges for the same reason you build bridges, because they are useful. We cannot help the fact that our universe is very strange. We envy your bridges that always lead to the same place and your parts that do not become black holes. From what you told us of your world, your software builders are in the same situation as us. Give them our sympathy and our camaraderie."  With that, you return home with a far greater appreciation of what your programmer friends have to go through.&lt;br /&gt;&lt;br /&gt;Thus ends our journey to the alternate dimension. Unfortunately for software developers, this place actually exists for us. The Halting Problem shows that we can never be certain of any result about any computation. It may run properly, it may become an endless loop, or it may give the completely wrong result. Adding concurrency adds on even more uncertainty into the situation. And we can PROVE this logically. There is no escape from the Halting Problem weirdness. Every single line of code added may blow up the bridge, dump you in China, or create a black hole.&lt;br /&gt;&lt;br /&gt;THAT is the real bridge to programmer metaphor. And it is why software development will always be hard.&lt;br /&gt;&lt;br /&gt;Now to help you all remember allow me to coin Gleason's Law:&lt;br /&gt;&lt;br /&gt;"Any sufficiently complex software is indistinguishable from magic."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-4305328426065118747?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/4305328426065118747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=4305328426065118747' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/4305328426065118747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/4305328426065118747'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/02/real-reason-why-building-software-is.html' title='The Real Reason Why Building Software is not like Building Bridges'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-7544266885939275747</id><published>2007-02-05T10:34:00.000-08:00</published><updated>2007-02-05T13:10:55.894-08:00</updated><title type='text'>Monads in Qi</title><content type='html'>It is hard to even begin to learn the cutting edge of functional language theory these days without talking about monads. In languages running in a purely functional manner, monads offer a way of dealing with the outside environment in a safe and controlled manner. In a pure environment, monads provide us a way to carry data computations via pure functional composition and still have computations that happen "on the side."  A lot of research into functional languages requires a solid understanding of monads and thus to apply their results to the Qi programming language, I'll define a few monad operations here and define a type theory that can handle the list monad&lt;br /&gt;&lt;br /&gt;Since you can find a wide variety of monads for the language Haskell, I will start by describing monads in Haskell and use that to define representations inside of the Qi language. Basically, a monad is a type that defines two operations. The operations are "lift" and "pipe". In Haskell, they are often called "return" and "bind" respectively. As long at the two functions hold the following identities, we can consider the type to be a monad.&lt;br /&gt;&lt;br /&gt;Here is a definition of the rules a monad must follow in a pure version of scheme.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   (pipe (lift x) f)   = (f x)&lt;br /&gt;   (pipe m lift)       = m&lt;br /&gt;   (pipe (pipe m f) g) = (pipe m (lambda (x) (pipe (f x) g)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In Haskell, the Monad m class is defined by&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Monad m where&lt;br /&gt;   return :: a -&gt; m a&lt;br /&gt;   (&gt;&gt;=)  :: m a -&gt; (a -&gt; m b) -&gt; m b&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can see that return "lifts" a value of type a into the monad class m a. Bind takes in a monad of type "a" and a function that takes in a value of type "a" and gives a monad of type "b". Bind then returns to us a monad of type "b" where the monad "a" has been transformed by the function into a monad of type "b". Once we have these two functions working as defined, we have a monad. Notice that we have not defined these functions yet. Haskell allows us to define a higher order type that we promise that all implementations of the type will have the listed functions and they will match the given type signatures. These sorts of definitions are not as easy in Qi, yet.&lt;br /&gt;&lt;br /&gt;One of the basic monad types in Haskell is the list monad. We define list monads as having type Monad [] and we can make a set of functions that follow the monad laws over Monad []'s.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;instance Monad [ ] where&lt;br /&gt;   (x:xs) &gt;&gt;= f = f x ++ (xs &gt;&gt;= f)&lt;br /&gt;   []     &gt;&gt;= f = []&lt;br /&gt;   return x     = [x]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Let us rewrite these rules in Qi.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define bind&lt;br /&gt;[] _ -&gt; []&lt;br /&gt;[X | Xs] F -&gt; (append (F X) (bind Xs F)))&lt;br /&gt;&lt;br /&gt;(define return&lt;br /&gt;X -&gt; [X]  )&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Well that was easy! Let us try out this new monad... We'll take a list of [10 20 30] and a function that takes an X and returns [X X+1] and give it to bind to see what it does with it.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(2-) (bind [10 20 30] (/. X [ X (+ X 1) ] ) )&lt;br /&gt;[10 11 20 21 30 31]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So far, so good. Let us check the monad laws to see if this version follows those laws. Law 1 says that (bind (return X) F) == (F X)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(5-) (define f X -&gt; [ X (+ X 1) ] )&lt;br /&gt;f&lt;br /&gt;&lt;br /&gt;(6-) (bind (return 2) f)&lt;br /&gt;[2 3]&lt;br /&gt;&lt;br /&gt;(7-) (f 2)&lt;br /&gt;[2 3]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Law 2 says (bind Monad return) == Monad&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(8-) (bind [ 4 5 6] return)&lt;br /&gt;[4 5 6]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Law 3 says that (bind (bind Monad F) G) = (bind Monad (/. X (pipe (F X) G)))&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(9-) (define g X -&gt; [ (+ X 33) (+ X 44) ] )&lt;br /&gt;g&lt;br /&gt;&lt;br /&gt;(10-) (bind (bind [10 20 30] f) g)&lt;br /&gt;[43 54 44 55 53 64 54 65 63 74 64 75]&lt;br /&gt;&lt;br /&gt;(11-) (bind [10 20 30] (/. X (bind (f X) g)))&lt;br /&gt;[43 54 44 55 53 64 54 65 63 74 64 75]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So we have proven that our monad list does in fact honor the monad laws. However, we are not running the type checker in Qi on this problem, so the monad we get is the same one that we can get in any functional language. We have to wait until runtime to see the error of the following attempt at using a monad.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(14-) (bind [10 20 a] (/. X (bind (f X) g)))&lt;br /&gt;1+: a is not a NUMBER&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So now the question becomes, can we get a monad into the TYPED version of Qi. Firstly, we must note that Qi has no notion of polymorphic type overloading. Hence we cannot easily make a general purpose "bind" operator that all monads can use. We also should note that the type checker treats a polymorphic list as a special case, and thus we cannot perform a direct translation like the one from Haskell. In some way, we will have to contain our lists in another type.&lt;br /&gt;&lt;br /&gt;Let us take the simplest translation. If something is of type (list A) then we can make a monadic list type of (monad list A) via the following sequent rules.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(datatype monad&lt;br /&gt;&lt;br /&gt;X : (list A);&lt;br /&gt;=====&lt;br /&gt;[X] : (monad list A);&lt;br /&gt;&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Monadic lists are simply lists inside of a container list and any list in a container can be a monad list of that type. We should read this as saying, "We can construct monads from lists by adding a list around it and we can construct lists from monads." We note that Qi allows you to go back from a monadic representation to the list based one as long as you properly use the type. Unfortunately, Qi has no notion of modules so we cannot seal off this behaviour from other functions in our code.&lt;br /&gt;&lt;br /&gt;Continuing, we will define some helper functions to allow us to manipulate the monad data structure inside the instance functions. Of course, Qi has no notion of either class or instance and allows us to pull lists from monads. But if we ignore these quirks for the moment, we can define a reasonable monad list type that works. I include a constructor function "list_monad" and a few internal data access helpers.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define list_monad&lt;br /&gt;{ (list A) --&gt; (monad list A) }&lt;br /&gt;X -&gt; [X] )&lt;br /&gt;&lt;br /&gt;(define m_head&lt;br /&gt;{ (monad list A) --&gt; A }&lt;br /&gt;X -&gt; (head (get_list X)))&lt;br /&gt;&lt;br /&gt;(define m_tail&lt;br /&gt;{ (monad list A) --&gt; (monad list A) }&lt;br /&gt;X -&gt; [ (tail (get_list X))] )&lt;br /&gt;&lt;br /&gt;(define m_cons&lt;br /&gt;{ A --&gt; (monad list A) --&gt; (monad list A) }&lt;br /&gt;X [Xs]-&gt; [(cons X Xs)])&lt;br /&gt;&lt;br /&gt;(define join&lt;br /&gt;{ (monad list (monad list A)) --&gt; (monad list A)}&lt;br /&gt;  Xs              -&gt; (join-help [[]] Xs))&lt;br /&gt;&lt;br /&gt;(define join-help&lt;br /&gt;{ (monad list A) --&gt; (monad list (monad list A)) --&gt; (monad list A) }&lt;br /&gt;Final [[]] -&gt; [ (reverse (get_list Final)) ]&lt;br /&gt;Final ML -&gt; (let XRest (m_tail (m_head ML))&lt;br /&gt;  (if (= XRest [[]])&lt;br /&gt;             (join-help (m_cons (m_head (m_head ML)) Final)&lt;br /&gt;                 (m_tail ML))&lt;br /&gt;             (join-help (m_cons (m_head (m_head ML)) Final)&lt;br /&gt;                              (m_cons (m_tail (m_head ML)) (m_tail ML))) )))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Our m_ functions  and join properly deal with getting (list A)'s from their containers and putting them back in. Join has to take the job of flatten and check for the end of a list and if we find it, drop it from the "Final" list. This accounts for the if statement in the function. It obviously makes heavy use of the data manipulation functions which lowers legability. We can read it as saying, "Take the first element head of the list (remember that we have a monad list of a monad lists here) and put it on the final list. Then take the rest of that head list and put it back on the processing queue. The Final output list is built in reverse order so we are forced to reverse the computation at the end of the join. Not pretty, but it works for the purpose of monad construction.&lt;br /&gt;&lt;br /&gt;Now we are in a position to define "bind" and "return" as before.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define bind&lt;br /&gt;{ (monad list A) --&gt; ( A --&gt; (monad list B)) --&gt; (monad list B) }&lt;br /&gt;XS F -&gt; (join [(map F (get_list XS)) ]))&lt;br /&gt;&lt;br /&gt;(define return&lt;br /&gt;{ A --&gt; (monad list A) }&lt;br /&gt;X -&gt; [[X]]&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that we basically take the list out of the monad container and apply normal list functions to it, wrapping it up back in the monad container when we return.&lt;br /&gt;&lt;br /&gt;Testing it out gives:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(14+) (bind (list_monad [10 20 30]) (/. X (list_monad [X (+ X 1)]) ))&lt;br /&gt;[[10 11 20 21 30 31]] : (monad list number)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And our monad type is certainly not a list&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(31+) (head (bind (list_monad [4 5 6]) return))&lt;br /&gt;error: type error&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now let us assure ourselves that our monad list is polymorphic to type A. We now define a fractal symbol function f.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(36+) (define f&lt;br /&gt;{ symbol --&gt; (monad list symbol) }&lt;br /&gt;X -&gt; (list_monad [ x o x]) where (= X x)&lt;br /&gt;_ -&gt; (list_monad [ o o o]))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And let us use it with our monad functions&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(37+) (bind (return x) f)&lt;br /&gt;[[x o x]] : (monad list symbol)&lt;br /&gt;&lt;br /&gt;(38+) (bind (bind (return x) f) f)&lt;br /&gt;[[x o x o o o x o x]] : (monad list symbol)&lt;br /&gt;&lt;br /&gt;(39+) (bind (bind (bind (return x) f) f) f)&lt;br /&gt;[[x o x o o o x o x o o o o o o o o o x o x o o o x o x]] : (monad list symbol)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So there you have it, a very simple, poorly performing basic list monad of polymorphic type A in the Qi Programming Language. Feel free to offer any questions or criticism that you have. Thanks for reading.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-7544266885939275747?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/7544266885939275747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=7544266885939275747' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/7544266885939275747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/7544266885939275747'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/02/monads-in-qi.html' title='Monads in Qi'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-6783464335278879737</id><published>2007-01-26T01:18:00.000-08:00</published><updated>2007-01-26T06:45:20.024-08:00</updated><title type='text'>Computing During Typing</title><content type='html'>I'm going to take another dive here into the Qi type system to give an idea of the expressive power possible in it. Qi has a fully Turing capable type system and that means that we should be able to express truths about natural numbers directly in the form of types. The computation of the truth will happen at compile time! For the purposes of this exercise, we will define "truth" as having matched to type "has_truth" and we will define falsehood as having raised a type_error or returning _|_ as represented by an infinite loop.&lt;br /&gt;&lt;br /&gt;We will start by encoding the Peano axioms into a Qi type. We will represent the natural numbers and truth as Qi Types. Then we will define the basic rules of arithmetic and describe the basics of everybody's favorite commutative semigroup. Finally, we will discuss falsehood and how Qi handles it, along with infinite loops, blown stacks, and some other real world programming issues.&lt;br /&gt;&lt;br /&gt;As a quick refresher for those of you not well versed in sequent notation, you can think of them as saying "If the top parts have these types, THEN the bottom construction is valid for the labeled type." Or alternatively, you can think of them as saying, "If we have a type that looks like one on the bottom, AND if we can take the components of it and prove them of types on the top, THEN we can type the bottom element as labeled." Now I'm not so certain my explanation helps...&lt;br /&gt;&lt;br /&gt;For Peano's first axiom, let us define the natural numbers as 0 and its successors labeled as [suc X] where X is a natural number. We include 0 as a convenience here, but it would be possible to define the type without it. We also include the sixth axiom here, namely the idea of successors which are represented as nested lists.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;___&lt;br /&gt;zero : nat;&lt;br /&gt;&lt;br /&gt;X : nat;&lt;br /&gt;=======&lt;br /&gt;[suc X] : nat;&lt;br /&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Taking his second axiom, let us ensure that every natural number is equal to itself. Note that this imports the notion of lexical equivalence from Qi into our type theory, but as = will always return, we can be assured that it is not going to cause any indefinite delay in the type theory. And it is in equality that we wish to test for truthhood, so we will need to define the type "has_truth" here.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if(= A1 A2)&lt;br /&gt;A1 : nat ; A2 : nat;&lt;br /&gt;===========&lt;br /&gt;[ A1 = A2 ] : has_truth;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In effect, we are saying that equal things "have truth." Alternatively, I could have named the type is_equals. Read it however you like.&lt;br /&gt;&lt;br /&gt;Peano's third axiom will end up causing no end to our headaches inside the Qi type system while giving us our expressiveness at the same time. It says A = B iff B = A.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[ A = B ] : has_truth;&lt;br /&gt;======&lt;br /&gt;[ B = A ] : has_truth;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We can drop the forth axiom due to us using a 2 sided system. Then using the fifth we find that if a = b is true and b is a natural number then a is a natural number. Given that A = B is true and B is a natural number, we can prove A is a natural number.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[ A = B ] : has_truth; B : nat;&lt;br /&gt;______&lt;br /&gt;A : nat;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Having already listed the sixth earlier, we turn to the seventh Peano axiom, the equality of successors. This axiom, unlike the third axiom, really simplifies the job that the type checker has to do. I like the seventh Axiom. It's not like that mean, mean third axiom. It makes me wonder how much math do you have to do in order to find some of Peano's axiom's more "friendly" than others. I see a Psych 101 experiment there. *grin*&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[A = B] : has_truth;&lt;br /&gt;_____&lt;br /&gt;[[suc A] = [suc B]] : has_truth;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;With the setup I used, we have no way of returning "not" so we have trouble with Peano's eighth axiom. It is sufficient to point out that we have imported the equality operator from Qi for which this property holds. So Axiom 2's code is our key here. And for this code, we can obviously leave out the ninth.&lt;br /&gt;&lt;br /&gt;On to the group operator +...&lt;br /&gt;&lt;br /&gt;We define a new type of number that is the result of addition.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;A : nat ; B : nat;&lt;br /&gt;========&lt;br /&gt;[ A plus B ] : nat ;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we can create the zero-to-identity rule which states that nothing changes when we add 0 to other numbers.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;A : nat;&lt;br /&gt;=======&lt;br /&gt;[A = [ A plus zero ]] : has_truth;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we must create the plus-to-successor rule that allows us to define addition over other numbers. We state that a + Sb = S ( a + b).&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;A : nat ; B : nat;&lt;br /&gt;[ C = [suc [ A plus B] ] ] : has_truth;&lt;br /&gt;====&lt;br /&gt;[ [A plus [suc B]] = C ] : has_truth;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that here we actually use an assignment to a variable to introduce a new equation. The best way of thinking of this equation is from the bottom up. If we are trying to find out the truth of an equation with a plus in it which does NOT have a zero, then we must find a new equation C that has one of our numbers subtracted by one, and take the successor of THAT.&lt;br /&gt;&lt;br /&gt;The real trick is to notice that C is a completely new construction created by our type system. The top part of the equation acts as a hypothetical that the proof checker then tries to solve. Peano's beloved seventh rule helps us find computable theorems even with an automated prover.&lt;br /&gt;&lt;br /&gt;So what do we get for all this? We get a type that can perform numerical computations at compile time!&lt;br /&gt;&lt;br /&gt;Lets try 0 = 0&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[ zero = zero ] : has_truth&lt;br /&gt;______________________________________________ 9 inferences&lt;br /&gt;?- [zero = zero] : has_truth&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 62 inferences&lt;br /&gt;?- zero : nat&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 112 inferences&lt;br /&gt;?- zero : nat&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;[zero = zero] : has_truth&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So far, that went swimmingly! Lets try something harder. S( 0 + 1) = 2.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(8+) [ [suc [ zero plus [ suc zero] ]] = [suc [ suc zero]] ] : has_truth&lt;br /&gt;______________________________________________ 9 inferences&lt;br /&gt;?- [[suc [zero plus [suc zero]]] = [suc [suc zero]]] : has_truth&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 71 inferences&lt;br /&gt;?- [[zero plus [suc zero]] = [suc zero]] : has_truth&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 138 inferences&lt;br /&gt;?- zero : nat&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 188 inferences&lt;br /&gt;?- zero : nat&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 238 inferences&lt;br /&gt;?- [[suc zero] = [suc [zero plus zero]]] : has_truth&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 300 inferences&lt;br /&gt;?- [zero = [zero plus zero]] : has_truth&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 363 inferences&lt;br /&gt;?- zero : nat&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;[[suc [zero plus [suc zero]]] = [suc [suc zero]]] : has_truth&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That worked great! We can see the proof tool using Peano's seventh like it was born to formalize! (Being a lambda calculus, it was. *grin*)&lt;br /&gt;&lt;br /&gt;Lets take on 3 + 2 = 5&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(9+)&lt;br /&gt;[ [ [suc [suc [suc zero]]] plus [suc [suc zero]] ] =&lt;br /&gt;[suc [suc [suc [suc [suc zero]]]]] ] : has_truth&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This gives us has_truth in 1081 inferences. The type checker does 5 = 3 + 2 in 363 steps.&lt;br /&gt;&lt;br /&gt;I mentioned that I'd wrap up on some real world issues. Since the type checker can insert any rule it needs to and search for ways to make the theorems work, we have a Turing complete type system. And this means that some things will never complete their type checking. So we have to explicitly deal with the _|_ type in some manner to get sensible behaviour out of the system.&lt;br /&gt;&lt;br /&gt;For example, let us take Peano's eighth axiom of zero != [suc zero]. If we ask this type theory about [zero = [suc zero]] : has_truth, it will have to either fail or return _|_. Unfortunately for us, the need for Peano's third axiom dooms us to get a _|_ style value back from the type checker, i.e. it never completes.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 222 inferences&lt;br /&gt;?- [[suc zero] = zero] : has_truth&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&lt;br /&gt;______________________________________________ 293 inferences&lt;br /&gt;?- [zero = [suc zero]] : has_truth&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This particular example is an area where the Qi type checker should probably understand that calling the same definition that you just called and failed to type before is a mistake. But any automated system will only recognize a small subset of these sorts of errors, so Qi's failure to type_error here is forgivable in these pathological types.&lt;br /&gt;&lt;br /&gt;So typing can blow the stack, (as in this case), or it can fail to type raising a type_error. Either of these we can use as falsehoods. If we wanted to extend the system further, we could encode negation into the system and have the ability to return True, False or a _|_ style answer.&lt;br /&gt;&lt;br /&gt;I hope this sheds some light into the Qi type system. There's a lot more you can do with it obviously. Hopefully you enjoyed the article and hopefully I can find time to post more.&lt;br /&gt;&lt;br /&gt;Best wishes,&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-6783464335278879737?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/6783464335278879737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=6783464335278879737' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/6783464335278879737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/6783464335278879737'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2007/01/calculating-during-typing.html' title='Computing During Typing'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-114784474483957966</id><published>2006-05-16T22:27:00.000-07:00</published><updated>2006-05-16T22:45:44.853-07:00</updated><title type='text'>Qi Macros and Type Patterns</title><content type='html'>Taking a step back to the &lt;a href="http://programmingkungfuqi.blogspot.com/2006/04/qi-and-magic-prime-type.html"&gt; Magic Prime Type&lt;/a&gt;, we find that the pattern that we used to generate the prime type may be useful to encapsulate in some manner. The pattern goes as follows: If you have a base class like number, and you have a derived class such as prime, then you can create these "prime like" classes as long as you have a function that returns true for the basic and derived type. Simply put, if we could just swap different lexical elements into our prime datatype constructor, we could have a useful piece of code for creating exotic types such as the “even” type or perhaps the “catalan” type. Obviously, when we talk about placing lexical elements inside of code, we are talking macros!&lt;br /&gt;&lt;br /&gt;So what would the Lisp-like macro look like for our “subtype-with-test” function? Something like the following, only better.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(DEFMACRO subtype-with-test ( BaseType NewType BaseTest NewTest)&lt;br /&gt;`(datatype ,NewType&lt;br /&gt;   if(and ( ,BaseTest X ) ( ,NewTest X ) )&lt;br /&gt;   ____&lt;br /&gt;   X : ,NewType ;&lt;br /&gt;&lt;br /&gt;   ___&lt;br /&gt;   ( ,NewTest X) : verified &gt;&gt; X : ,NewType ;&lt;br /&gt;&lt;br /&gt;   ( subtype B A ) ; X : B ;&lt;br /&gt;   ___&lt;br /&gt;   X : A;&lt;br /&gt;&lt;br /&gt;   ___&lt;br /&gt;   (subtype ,NewType ,BaseType);&lt;br /&gt; )&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However, if you try to input that into Qi, you’ll find it will not make a compiling as something seems to happen to the ;. We need to use the "macroexpand" function mentioned in Appendix B of FPIQ language book. Fortunately for us, the syntax makes our final Qi macro a bit easier to read than the lisp version. We first create a pattern that looks like a function call that matches our macro. We’ll name it the same as above and it will take the same arguments.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define macroexpand&lt;br /&gt;  [subtype-with-test BaseType NewType BaseTest NewTest] -&gt;&lt;br /&gt;  [datatype NewType&lt;br /&gt;    if[and [ BaseTest X ]&lt;br /&gt;           [ NewTest X ]]&lt;br /&gt;    ______&lt;br /&gt;    X : NewType ;&lt;br /&gt;&lt;br /&gt;    ____&lt;br /&gt;    [ NewTest X ] : verified &gt;&gt; X : NewType ;&lt;br /&gt;&lt;br /&gt;   [ subtype B A ] ; X : B ;&lt;br /&gt;   ___&lt;br /&gt;   X : A;&lt;br /&gt;   &lt;br /&gt;    ___&lt;br /&gt;   [ subtype NewType BaseType ]; ]&lt;br /&gt;   X -&gt; X&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And that’s all there is to it! Just remember to make sure to include the X-&gt; X pattern at the bottom. Every single token receives a macroexpand so we need to ensure that it works as intended for all but our special "subtype-with-test" macro. Note that the pattern match serves as our macro definition. We define it in no other place.&lt;br /&gt;&lt;br /&gt;Now doing the following creates a brand new type!&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(subtype-with-test number prime integer? prime?)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We should note that the macroexpanded "subtype-with-test" prevents the evaluation of the 4 inputs. So we find the typical problem with variable capture. We don’t have the ability to name our classes X, A, or B!!! *laugh* Not a big loss, but we can modify the code and learn to deal with variable capture. We do this in the same way we deal with it in Lisp, namely gensyms.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;define macroexpand&lt;br /&gt;  [subtype-with-test BaseType NewType BaseTest NewTest] -&gt;&lt;br /&gt;  (let X (gensym "Temp")&lt;br /&gt;  (let A (gensym "Temp")&lt;br /&gt;  (let B (gensym "Temp")&lt;br /&gt;  [datatype NewType&lt;br /&gt;    if[and [ BaseTest X ]&lt;br /&gt;           [ NewTest X ]]&lt;br /&gt;    ______&lt;br /&gt;    X : NewType ;&lt;br /&gt;&lt;br /&gt;    ____&lt;br /&gt;    [ NewTest X ] : verified &gt;&gt; X : NewType ;&lt;br /&gt;&lt;br /&gt;   [ subtype B A ] ; X : B ;&lt;br /&gt;   ___&lt;br /&gt;   X : A;&lt;br /&gt;   &lt;br /&gt;    ___&lt;br /&gt;   [ subtype NewType BaseType ]; ] )))&lt;br /&gt;   &lt;br /&gt;   X -&gt; X&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;One important point to note is that the "Temp" (or whatevever you want to name your gensym) must start in UPPER CASE! Otherwise, Qi won’t be able to tell it is a variable! &lt;br /&gt;&lt;br /&gt;Qi does warn about these sorts of issues however, if you see the free variable warning in a macro, capture them with gensyms to turn this sort of output …&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(0-) (load "test/pmacro2.qi")&lt;br /&gt;======&gt; Warning:&lt;br /&gt;the following variables are free in macroexpand: B; X; A;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;WARNING:&lt;br /&gt;DEFUN/DEFMACRO: redefining function macroexpand in D:\tools\Qi 6.2\startup_qi.tx&lt;br /&gt;t, was defined in D:\tools\Qi 6.2\Install Qi\Qi 6.3.txtmacroexpand&lt;br /&gt;&lt;br /&gt;Real time: 0.0156303 sec.&lt;br /&gt;Run time: 0.015625 sec.&lt;br /&gt;Space: 185740 Bytes&lt;br /&gt;loaded&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;into this much nicer output…&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(0-) (load "test/pmacro3.qi")&lt;br /&gt;&lt;br /&gt;WARNING:&lt;br /&gt;DEFUN/DEFMACRO: redefining function macroexpand in D:\tools\Qi 6.2\startup_qi.tx&lt;br /&gt;t, was defined in D:\tools\Qi 6.2\Install Qi\Qi 6.3.txtmacroexpand&lt;br /&gt;&lt;br /&gt;Real time: 0.0312606 sec.&lt;br /&gt;Run time: 0.03125 sec.&lt;br /&gt;Space: 194036 Bytes&lt;br /&gt;Loaded&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note the lack of compiler warnings about free variables. However it will always warn you about redefining macroexpand. Of course, since we are defining VARIABLES in the datatype, no real variable capture can happen. Our macro requires lower case symbols to even operate. But this example shows how to avoid the issue in the odd case where you want to make a macro that you can define different variable names inside it. (Can anyone think of a good reason to do this?)&lt;br /&gt;&lt;br /&gt;So let us try this new macro out! We’ll create an even test and create a new type called "even" that can only type to actual even numbers.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(12+)  (define even?&lt;br /&gt;{ number --&gt; boolean }&lt;br /&gt;X -&gt; (integer? (/ X 2)) )&lt;br /&gt;even? : (number --&gt; boolean)&lt;br /&gt;&lt;br /&gt;(13+) (subtype-with-test number even integer? even?)&lt;br /&gt;even : unit&lt;br /&gt;&lt;br /&gt;(14+) 3 : even&lt;br /&gt;error: type error&lt;br /&gt;&lt;br /&gt;(15+) 4 : even&lt;br /&gt;4 : even&lt;br /&gt;&lt;br /&gt;(16+)  100 : even&lt;br /&gt;100 : even&lt;br /&gt;&lt;br /&gt;(17+) 101 : even&lt;br /&gt;error: type error&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I’d say that is an impressive job for one line of code! Let me know what you think!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-114784474483957966?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/114784474483957966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=114784474483957966' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114784474483957966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114784474483957966'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2006/05/qi-macros-and-type-patterns.html' title='Qi Macros and Type Patterns'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-114775372662417432</id><published>2006-05-15T21:21:00.000-07:00</published><updated>2006-05-16T04:58:32.366-07:00</updated><title type='text'>Treaps in Qi</title><content type='html'>Delving back into the type system for this post, I thought I would take on the strange and wonderful Binary Search Tree known as the treap.  For those that don’t know, a treap is a binary search tree that has a “priority” element attached to the key. It uses the random priority to ensure balancing of the tree. It does this by ensuring the tree is in binary search tree form with respect to the keys, and in heap form with respect to the priorities. We will create a simple type of string based treap in Qi and perhaps extend it to a more general version if I find the time to finish it. *grin*&lt;br /&gt;&lt;br /&gt;The datatype for treap can be either list based or tuple based. I’ll begin with the tuple version as it shows off a bit more of the power of Qi pattern matching, but a list version would be more readable. We can signify empty leaves with the null list in either case.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;_______&lt;br /&gt;[] : treap;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And now we will create the recursive type. It takes a key and a priority and has a left branch and a right branch. Using the tuple to define the leaves means we place the key and priority in their own tuple and use that as the first element. Then we can put the left and right branches in their own tuple as the second element of our treap node. We’ll use the ever handy left/right sequent operator to ensure we can prove things about treaps using the datastructure only and typing the internal parts.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Key : string; Priority : number; LeftTreap : treap; RightTreap : treap;&lt;br /&gt;===============================&lt;br /&gt;(@p (@p Key Priority) (@p LeftTreap RightTreap)) : treap;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now when we wish to insert a key into the treap, we must first make a random number to assign it for heap priority.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define treap_insert&lt;br /&gt;{string --&gt; treap --&gt; treap}&lt;br /&gt;K Tree -&gt; (treap_insert* K (- (random 40000000) 20000000) Tree))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now the fun begins. The base case seems simple enough, just make a treap that looks like the above definition but has LeftTreap and RightTreap set to [].&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define treap_insert*&lt;br /&gt;{string --&gt; number --&gt; treap --&gt; treap}&lt;br /&gt;K P [] -&gt; (@p (@p K P) (@p [] []))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now it could be that we are trying to insert an element that we already have. If so, we simply return the treap we had to begin with.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;K P (@p (@p K* P*)&lt;br /&gt;  (@p L R))&lt;br /&gt;-&gt; (@p (@p K* P*) (@p L R)) where (= K K*)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that our pattern matched definition is well typed. L is a treap and R is a treap. K is a string and P is a number. We match the new key and priority as K and P. We match the treap node’s priority as K* and P* and the branches as L and R. If you mess up using them in your definition, the complier complains loudly.&lt;br /&gt;&lt;br /&gt;Now we know the K is not equal to the current treap node, if it is less than the tree node we insert it somewhere on the left tree. AFTER we do this, then we order the treap by heap priority, preserving the BST ordering as we move our way up the tree. We’ll use the same pattern as the element above.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;K P (@p (@p K* P*)&lt;br /&gt;  (@p L R))&lt;br /&gt;-&gt; (let Tree (@p (@p K* P*)&lt;br /&gt;             (@p (treap_insert* K P L)&lt;br /&gt;     R))&lt;br /&gt;    (if (&gt; P* P)&lt;br /&gt;   (rotate_right Tree)&lt;br /&gt;   Tree))&lt;br /&gt;&lt;br /&gt;    where(str-lt K K*)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So if our new priority is less than the old one, we move it up the treap. That makes it reverse heap ordering, but we are not splitting hairs here. *grin*&lt;br /&gt;&lt;br /&gt;So now we need to find out how to rotate a treap node up a treap. Rotate right takes the L branch and finds its left and right treaps and their keys. It then puts the left L treap as the current left, uses the left treap node’s key/priority as the current key/priority and makes a new right treap with the original left nodes right hand treap paired with the old right hand side, placing the old key/priority there. The code below serves as our heapify.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define rotate_right&lt;br /&gt;  {treap --&gt; treap}&lt;br /&gt;(@p (@p Key Priority)&lt;br /&gt;    (@p (@p (@p K* P*)&lt;br /&gt;       (@p A1 A2))&lt;br /&gt;   B))&lt;br /&gt;&lt;br /&gt;-&gt; (@p (@p K* P*)&lt;br /&gt;  (@p A1&lt;br /&gt;      (@p (@p Key Priority)&lt;br /&gt;   (@p A2 B)) ))&lt;br /&gt;    &lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Pattern matching makes the change short and sweet. Type checking ensures that we have a valid treap at the end.&lt;br /&gt;&lt;br /&gt;Now we can finish our definition of treap_insert with the right hand insert&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;K P (@p (@p K* P*)&lt;br /&gt;  (@p L R))&lt;br /&gt;&lt;br /&gt;-&gt; (let Tree (@p (@p K* P*)&lt;br /&gt;        (@p L&lt;br /&gt;     (treap_insert* K P R)))&lt;br /&gt;    (if (&gt; P* P)&lt;br /&gt;   (rotate_left Tree)&lt;br /&gt;   Tree))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can make a rotate_left along the lines of the rotate_right&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define rotate_left&lt;br /&gt;{treap --&gt; treap}&lt;br /&gt;(@p (@p Key Priority)&lt;br /&gt;    (@p A&lt;br /&gt;        (@p (@p K* P*)&lt;br /&gt;       (@p B1 B2))))       -&gt; (@p (@p K* P*)&lt;br /&gt;      (@p&lt;br /&gt;         (@p (@p Key Priority)&lt;br /&gt;      (@p A B1))&lt;br /&gt;          B2))&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;All we need to do now is define a string less than function str-lt that compares strings. And here we run into a problem. We have no type safe way of comparing strings in Qi.  So we’ll have to modify Qi to know about our version of the string compare function. We’ll build it from the ground up by giving CHAR-CODE a type. In deference to Haskell, let us name the function “ord”.&lt;br /&gt;&lt;br /&gt;You can patch it with&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;42c42&lt;br /&gt;&lt;&gt;    occurrences occurs-check or output prf print profile profile-results prooft&lt;br /&gt;ool provable?&lt;br /&gt;47c47&lt;br /&gt;&lt;&gt;    track tuple? undebug unprf union unprofile untrack value version&lt;br /&gt;1527c1527&lt;br /&gt;&lt;&gt;     number? 1 occurs-check 1 occurrences 2 or 2 prf 1 print 1 profile 1 profil&lt;br /&gt;e-results 1 prooftool 1&lt;br /&gt;1586,1587c1586&lt;br /&gt;&lt;     (boolean --&gt; (boolean --&gt; boolean)) ord (character --&gt; number)&lt;br /&gt;&lt;&gt; B) --&gt; (A --&gt; B))&lt;br /&gt;---&lt;br /&gt;&gt;     (boolean --&gt; (boolean --&gt; boolean)) prf ((A --&gt; B) --&gt; (A --&gt; B))&lt;br /&gt;2397,2398d2395&lt;br /&gt;&lt; (DEFUN ord (x) (CHAR-CODE x)) &lt;&gt; string --&gt; boolean}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But it would help to simply search for the word “difference” as it is an internal function used only 3 times in the program outside its own definition and add the code yourself to learn how. There you find the arity list that you must add the ord function too and the type list where you specify the type. Then you can add the DEFUN for ord by the other system function defuns. Run the installer and you will get a version of Qi that has our “ord” function.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;--- EDIT ---&lt;br /&gt;&lt;br /&gt;I'm adding a much better way of doing this in Qi that Mark pointed out on the mailing list.&lt;br /&gt;&lt;br /&gt;Lisp contains a function STRING&lt;, so if you want to bring this into Qi,&lt;br /&gt;then the following will do it.&lt;br /&gt;&lt;br /&gt;(0-) (define string&lt;&lt;br /&gt;    X Y -&gt; (if (empty? (STRING&lt; X Y)) false true))&lt;br /&gt;======&gt; Warning:&lt;br /&gt;the following variables are free in string&lt;: STRING&lt;;&lt;br /&gt;string&lt;&lt;br /&gt;&lt;br /&gt;(1-) (newfuntype string&lt; (string --&gt; string --&gt; boolean))&lt;br /&gt;string&lt;&lt;br /&gt;&lt;br /&gt;(2-) (tc +)&lt;br /&gt;true&lt;br /&gt;&lt;br /&gt;(3+) string&lt;&lt;br /&gt;string&lt; : (string --&gt; (string --&gt; boolean))&lt;br /&gt;&lt;br /&gt;(4+) (string&lt; "ghgjj" "ghhhg")&lt;br /&gt;true : boolean &lt;br /&gt;&lt;br /&gt;--- EDIT END ---&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we can define our string less than function, “str-lt”.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define str-lt&lt;br /&gt;  {string --&gt; string --&gt; boolean}&lt;br /&gt;  S1 S2 -&gt; (str-lt* (explode S1) (explode S2)))&lt;br /&gt;&lt;br /&gt;(define str-lt*&lt;br /&gt; {(list character) --&gt; (list character) --&gt; boolean}&lt;br /&gt;  [] _  -&gt; false&lt;br /&gt;  _  [] -&gt; true&lt;br /&gt;  [X |_] [Y | _] -&gt; true where (&lt; (ord X) (ord Y))&lt;br /&gt;  [_ |L1] [_ | L2] -&gt; (str-lt* L1 L2)&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And now we have a working, input-only treap. I think at this point I will take a break and perhaps return the program efficiency and changing of the syntax in another article. Let me know of any questions or comments you have so far please!&lt;br /&gt;&lt;br /&gt;Here is the full file. I'll create a place to download my code sometime soon.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(datatype treap&lt;br /&gt;&lt;br /&gt;  _______&lt;br /&gt;  [] : treap;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  Key : string; Priority : number; LeftTreap : treap; RightTreap : treap;&lt;br /&gt;  ===============================&lt;br /&gt;  (@p (@p Key Priority) (@p LeftTreap RightTreap)) : treap;&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define treap_empty?&lt;br /&gt;  { treap --&gt; boolean }&lt;br /&gt;  Tree -&gt; true where (= Tree [])&lt;br /&gt;  Tree -&gt; false&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(define rotate_left&lt;br /&gt;  {treap --&gt; treap}&lt;br /&gt;  (@p (@p Key Priority) &lt;br /&gt;      (@p A&lt;br /&gt;          (@p (@p K* P*)&lt;br /&gt;       (@p B1 B2))))       -&gt; (@p (@p K* P*)&lt;br /&gt;      (@p &lt;br /&gt;         (@p (@p Key Priority)&lt;br /&gt;      (@p A B1))&lt;br /&gt;          B2))&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(define rotate_right&lt;br /&gt;    {treap --&gt; treap}&lt;br /&gt;  (@p (@p Key Priority) &lt;br /&gt;      (@p (@p (@p K* P*)&lt;br /&gt;       (@p A1 A2))&lt;br /&gt;   B))&lt;br /&gt; &lt;br /&gt;  -&gt; (@p (@p K* P*)&lt;br /&gt;  (@p A1&lt;br /&gt;      (@p (@p Key Priority)&lt;br /&gt;   (@p A2 B))&lt;br /&gt;      ))&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(define treap_insert&lt;br /&gt; {string --&gt; treap --&gt; treap}&lt;br /&gt; K T -&gt; (treap_insert* K (- (random 40000000) 20000000) T))&lt;br /&gt;&lt;br /&gt;(define treap_insert*&lt;br /&gt;  {string --&gt; number --&gt; treap --&gt; treap}&lt;br /&gt; K P [] -&gt; (@p (@p K P) (@p [] []))&lt;br /&gt;&lt;br /&gt; K P (@p (@p K* P*)&lt;br /&gt;  (@p L R))  &lt;br /&gt; -&gt; (@p (@p K* P*) (@p L R)) where (= K K*)&lt;br /&gt;&lt;br /&gt; K P (@p (@p K* P*)&lt;br /&gt;  (@p L R))  &lt;br /&gt; -&gt; (let Tree (@p (@p K* P*)&lt;br /&gt;               (@p (treap_insert* K P L) &lt;br /&gt;     R))&lt;br /&gt;      (if (&gt; P* P)&lt;br /&gt;   (rotate_right Tree)&lt;br /&gt;   Tree))&lt;br /&gt;    &lt;br /&gt;    where(str-lt K K*)&lt;br /&gt;&lt;br /&gt; K P (@p (@p K* P*)&lt;br /&gt;  (@p L R)) &lt;br /&gt;&lt;br /&gt; -&gt; (let Tree (@p (@p K* P*)&lt;br /&gt;        (@p L&lt;br /&gt;     (treap_insert* K P R)))&lt;br /&gt;      (if (&gt; P* P)&lt;br /&gt;   (rotate_left Tree)&lt;br /&gt;   Tree))&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define str-lt&lt;br /&gt;  {string --&gt; string --&gt; boolean}&lt;br /&gt;  S1 S2 -&gt; (str-lt* (explode S1) (explode S2)))&lt;br /&gt;&lt;br /&gt;(define str-lt*&lt;br /&gt; {(list character) --&gt; (list character) --&gt; boolean}&lt;br /&gt;  [] _  -&gt; false&lt;br /&gt;  _  [] -&gt; true&lt;br /&gt;  [X |_] [Y | _] -&gt; true where (&lt; (ord X) (ord Y))&lt;br /&gt;  [_ |L1] [_ | L2] -&gt; (str-lt* L1 L2)&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-114775372662417432?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/114775372662417432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=114775372662417432' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114775372662417432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114775372662417432'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2006/05/treaps-in-qi.html' title='Treaps in Qi'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-114715215925467930</id><published>2006-05-08T22:17:00.000-07:00</published><updated>2006-05-08T22:26:13.820-07:00</updated><title type='text'>Qi Optimization and Catalan Fun!</title><content type='html'>We start this week by delving a bit into number theory and seeing what we can accomplish with Qi. We will start with a simple approach to the problem and then perform some optimizations on our program. We will use pattern matching, backtracking, and arrays to enhance the performance of our sequence in order to better understand Qi. Hopefully, this process will show the powers of Qi to search complicated number spaces and what limitations we run into when using Qi in general as well.&lt;br /&gt;&lt;br /&gt;Let us start with the empty string, "". We can define this as 0. If we put a pair of parenthesis around the empty string, we get the new string "()". We can call this string 1. Putting a pair of parenthesis around the 1 gives us "(())" or what we will call 2. Alternatively, we can concatenate 1 to 1 to get another version of the string, "()()". Doing this for 3 gives us "((()))" , "()()()" , "(()())", "(())()" and "()(())". These obviously represent basic addition facts if you think of concatenation as + and the parenthesis as + 1. Or we can think of these strings as the number of ways we can parenthesize a string of length N.  We have defined these strings via 2 basic operations, either by interning previous strings with parenthesis or by either concatenation be it left-handed or right-handed. This feels reminiscent of the S and K combinators, but perhaps that’s a topic for another time. &lt;br /&gt;&lt;br /&gt;So from that description, we can devise a simple Qi program to output those strings. We will call this function get-cstrings. The base case is 0 and we define it as the empty string.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define get-cstrings&lt;br /&gt;0 -&gt; [""]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now for the recursive case, we either perform the "interning" operation by putting a pair of parentheses around the previously created number, or by taking any previous number combination that adds to our number and concatenating them together. We define the intern function as intern-all which takes a list of strings and interns each string. We also define the left and right concatenation function as lr-apply. It takes in the interned strings and adds the concatenation strings to it.  This gives us the full function definition as follows.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define get-cstrings&lt;br /&gt;  0   -&gt; [""]&lt;br /&gt;  N   -&gt; (let NewList (intern-all (get-cstrings (- N 1) ))&lt;br /&gt;           (lr-apply N NewList))&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Turing to intern all, we need to take a list and add the parentheses around each element. So we use map to apply a function across the list. The function should take a string, and add parentheses around the front and back. Using this opportunity to apply the Lisp underbelly of Qi seems fun at this point, and gives us more to optimize later. So we take the string, turn it into a list, append the parentheses, and then turn it back into a string.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define intern-all&lt;br /&gt;  Xs -&gt; &lt;br /&gt;       (map&lt;br /&gt;          (/. Elem &lt;br /&gt;             (COERCE (append [ #\( | (COERCE Elem LIST) ] [ #\) ] ) STRING)) &lt;br /&gt;          Xs&lt;br /&gt;       )&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Turing our attention to lr-apply now, we note that it walks from 1 up to n-1, forming new strings from pairs of older strings by concatenating them to each other. So we will start with lr-apply&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define lr-apply &lt;br /&gt;  0 Xs  -&gt; Xs&lt;br /&gt;  N Xs -&gt; (lr-apply* 1 (- N 1) Xs))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And now we need to define the recursive lr-apply* that creates these strings. It takes in the left number and the right number, along with the strings we have built so far. It adds the new strings to the final list. When the right number becomes greater than the left number, we stop.  Using the helper function lr-work, we try the following definition.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define lr-apply*&lt;br /&gt;  L R Final -&gt;&lt;br /&gt;   (let A (get-cstrings L)&lt;br /&gt;   (let B (get-cstrings R)&lt;br /&gt;        (lr-apply* (+ L 1) (- R 1) (lr-work A B Final))))&lt;br /&gt;    where (&gt;= R L)&lt;br /&gt;  _ _ Final -&gt; Final&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The lr-work function takes the left list of strings and the right list of strings and combines them and adds them to the final list. It uses a helper function pair-this to concatenate an element to each element of the second list. If we had access to the Haskell prelude, we could define this more concisely. You can check the google group for a beginning implementation.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define lr-work&lt;br /&gt; [] _ Final  -&gt; Final&lt;br /&gt; [X | Xs] Ys Final -&gt; (lr-work Xs Ys (pair-this X Ys Final))&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(define pair-this&lt;br /&gt;  _ [] Final -&gt; Final&lt;br /&gt;  X [Y|Xs] Final -&gt; (pair-this X Xs (make-ap-pair X Y Final))&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, we have a function called make-ap-pair that takes 2 strings and returns their left and right concatenation. It uses a helper function named give-unique to ensure that the element has not already been placed in the list. We’ll use the Lisp function concatenate instead of any Qi functions.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define make-ap-pair&lt;br /&gt; L-num R-num Xs -&gt; (let AfterLeft (give-unique [(CONCATENATE STRING L-num R-num)] Xs)&lt;br /&gt;                           (give-unique [(CONCATENATE STRING R-num L-num)] AfterLeft))&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(define give-unique&lt;br /&gt;  []  Xs             -&gt; Xs&lt;br /&gt;  [X | Left]  Xs  -&gt; (give-unique Left Xs) where (element? X Xs)&lt;br /&gt;  [X | Left ]  Xs  -&gt; (give-unique Left [ X | Xs ])&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Running this gives:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(2-) (get-cstrings 0)&lt;br /&gt;[""]&lt;br /&gt;&lt;br /&gt;(3-) (get-cstrings 1)&lt;br /&gt;["()"]&lt;br /&gt;&lt;br /&gt;(4-) (get-cstrings 2)&lt;br /&gt;["()()" "(())"]&lt;br /&gt;&lt;br /&gt;(5-) (get-cstrings 3)&lt;br /&gt;["(())()" "()(())" "()()()" "(()())" "((()))"]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This function obviously grows the list very quickly. Look at the following.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(6-) (LENGTH (get-cstrings 3))&lt;br /&gt;5&lt;br /&gt;&lt;br /&gt;(7-) (LENGTH (get-cstrings 4))&lt;br /&gt;14&lt;br /&gt;&lt;br /&gt;(8-) (LENGTH (get-cstrings 5))&lt;br /&gt;42&lt;br /&gt;&lt;br /&gt;(9-) (LENGTH (get-cstrings 6))&lt;br /&gt;132&lt;br /&gt;&lt;br /&gt;(10-) (LENGTH (get-cstrings 7))&lt;br /&gt;429&lt;br /&gt;&lt;br /&gt;(11-) (LENGTH (get-cstrings 8))&lt;br /&gt;1430&lt;br /&gt;&lt;br /&gt;(12-) (LENGTH (get-cstrings 9))&lt;br /&gt;4862&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And c-strings 9 starts to take some noticeable time on my personal box. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(13-) (time (LENGTH (get-cstrings 9)))&lt;br /&gt;&lt;br /&gt;Real time: 4.984375 sec.&lt;br /&gt;Run time: 4.953125 sec.&lt;br /&gt;Space: 3335576 Bytes&lt;br /&gt;GC: 6, GC time: 0.0 sec.4862&lt;br /&gt;&lt;br /&gt;(14-) (time (LENGTH (get-cstrings 10)))&lt;br /&gt;&lt;br /&gt;Real time: 63.984375 sec.&lt;br /&gt;Run time: 63.203125 sec.&lt;br /&gt;Space: 12635520 Bytes&lt;br /&gt;GC: 19, GC time: 0.0625 sec.16796&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Obviously, we want to do better. So let us note that the function calls the previous function many times. If we memorize the array, we can find the previous runs with no difficulty. We will use a global array to hold the strings up to 10 named *clst*. We use backtracking to check to see if we already have memorized the result, if not, we compute it.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define get-pstrings&lt;br /&gt;  0   -&gt; [""]&lt;br /&gt;  N   &lt;- (get-array (value *clst*) [N] #\Escape)&lt;br /&gt;  N   -&gt; (append (intern-all (get-pstrings (- N 1)) []) (lr-apply N []) ) where (&gt; N 10)&lt;br /&gt;  N   -&gt; (let NewList (intern-all (get-pstrings (- N 1)) [])&lt;br /&gt;         (let LrList (lr-apply N [])&lt;br /&gt;             (put-array (value *clst*) [N] (append NewList LrList) )))&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We can change the intern-all to make more sense and run much faster. Map ends up being slower than simply defining it recursively.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define intern-all&lt;br /&gt; [] Out -&gt; Out&lt;br /&gt; [X | Xs] Out -&gt; (intern-all Xs [(CONCATENATE STRING "(" X ")") | Out] )&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;These simple changes gives us twice the performance.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(10-) (time (LENGTH (get-pstrings 9)))&lt;br /&gt;&lt;br /&gt;Real time: 2.53125 sec.&lt;br /&gt;Run time: 2.515625 sec.&lt;br /&gt;Space: 730696 Bytes&lt;br /&gt;GC: 2, GC time: 0.015625 sec.4862&lt;br /&gt;&lt;br /&gt;(11-) (time (LENGTH (get-pstrings 10)))&lt;br /&gt;&lt;br /&gt;Real time: 33.609375 sec.&lt;br /&gt;Run time: 33.265625 sec.&lt;br /&gt;Space: 2969960 Bytes&lt;br /&gt;GC: 4, GC time: 0.03125 sec.16796&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Many more obvious improvements can be made, but that suffices to show how you can flesh out a correct answer then modify it for efficiency.&lt;br /&gt;&lt;br /&gt;Of course, if you took this sequence of integers and search for them you’ll find that this is a well known sequence called A000108,  Segner numbers, or more often Catalan numbers. &lt;a href="http://www.research.att.com/~njas/sequences/?q=132%2C429%2C1430&amp;sort=0&amp;fmt=0&amp;language=english&amp;go=Search"&gt;&lt;br /&gt;Our favorite number list &lt;/a&gt; has the following interesting definition.&lt;br /&gt;&lt;br /&gt;a(n) = binomial(2n, n)-binomial(2n, n-1)&lt;br /&gt;&lt;br /&gt;We can easily understand how the binomial(2n,n) is part of the result, as we have strings of N left parentheses and N right parentheses. We must choose equal pairs of parentheses so we have N as the bottom element of the function. However, we must remove the unbalanced parenthesis so we take out the incorrect elements via subtracting the number of strings that are "unbalanced" or one off of balanced. Hence we find the binomial (2n, n-1).&lt;br /&gt;&lt;br /&gt;However, if we think about this problem as we have programmed it above, we can come up with an equivalent definition that may help us understand the binomial function. In the program above, it takes the a(n-1) and interns each element, returning the same number. It then builds lists from combinations of previous results. So we have the equation&lt;br /&gt;&lt;br /&gt;a(n) = a(n-1) + some_binomial_function&lt;br /&gt;&lt;br /&gt;So let us determine what this binomial function turns out to be. Remembering Pascal’s rule of binomial(n-1,k)+binomial(n-1,k-1)=binomial(n,k) allows us to reduce the original definition into the following, with b for binomial.&lt;br /&gt;&lt;br /&gt;a(n) = b(2(n-1),n-1) + b(2(n-1),n-2) + b(2(n-1),n-1) + b(2(n-1),n) &lt;br /&gt;–b(2(n-1),n-3) - b(2(n-1),n-2)- b(2(n-1),n-2) - b(2(n-1),n-1)&lt;br /&gt;&lt;br /&gt;And remembering the b(n,r)=b(n,n-r) gives us the following reduction.&lt;br /&gt;&lt;br /&gt;a(n) = binomial(2(n-1), n-1) – binomial(2(n-1),n-3)&lt;br /&gt;&lt;br /&gt;So now we found part of an a(n-1), thus we can find our some_binomial_function from&lt;br /&gt;&lt;br /&gt;a(n) = binomial(2(n-1), n-1) –binomial(2(n-1),n-2) + some_binomial_function&lt;br /&gt;&lt;br /&gt;some_binomial_functions = binomial(2(n-1),n-2) – binomial(2(n-1),n-3)&lt;br /&gt;&lt;br /&gt;So we can see that the first part of the binomial function cancels out with the last part of the a(n-1) function, leaving only the final part as a subtraction. Thinking about what this "some_binomial_function" means, we can see that we take the substrings that we can add together to get a bigger substring, minus the number of invalid and duplicate substrings. This gives us the final version that computes our Qi functions output length.&lt;br /&gt;&lt;br /&gt;a(n) = a(n-1) + binomial(2(n-1),n-2) – binomial(2(n-1),n-3)&lt;br /&gt;&lt;br /&gt;Of course, we can make more optimizations and go further into the Catalan numbers, which I may do in the future. For now, I hope this serves as a fun introduction to Qi optimization and the always interesting Catalan sequence. Let me know what you think!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-114715215925467930?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/114715215925467930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=114715215925467930' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114715215925467930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114715215925467930'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2006/05/qi-optimization-and-catalan-fun.html' title='Qi Optimization and Catalan Fun!'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-114633196124745473</id><published>2006-04-29T10:31:00.000-07:00</published><updated>2006-04-29T10:32:41.256-07:00</updated><title type='text'>Building Lisp, Qi and other Fun Hacks</title><content type='html'>At some point when using Qi, you may find yourself wanting to do a bit more than the system provides natively. Perhaps you want to double click a .qi file and have it run in Qi. Perhaps you want to do some text processing and you need the CL-PPCRE regular expression library. If you do have either of those needs, you are in luck. I’ll explain how to do both in this article. But I'll try to keep an eye towards what's going on under the hood in Qi so we can better understand the motivation for this code.&lt;br /&gt;&lt;br /&gt;First, let us cover passing files to the Qi.bat file and having them run. This is equivalent to double clicking on a .qi file in windows explorer with the proper file type associations set. The current Qi.bat that comes with Qi 6.2 does not allow you to pass .qi files on the command line into Qi. If we look at Qi.bat, we find that it simply loads CLISP with the startup_qi.txt file on the command line as an argument. It has 2 lines &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(TERPRI)&lt;br /&gt;(qi::qi)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Terpri prints a newline to the output stream then calls the main (qi::qi) function. If we want our system to understand arguments, we will have to do it before the (qi::qi) line. This is because at that point, Qi takes over and we have lost our chance to get back to the arguments. What we need to do is initialize the qi environment ourselves and load our .qi file given on the command line. Finally, we can call (qi::qi) knowing our file has been loaded into the system. In the following, we find a load_n_launch function that does exactly this. Note that while the function is mostly written in Lisp, it can makes calls to the qi subsystem via the package operator. It is important to remember that even at this point we have entered a "Qi like" environment. To better understand why, we need to understand how Qi bootstraps itself.&lt;br /&gt;&lt;br /&gt;&lt;b&gt; The Qi Bootstrap - How to build your own Qi &lt;/b&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; Creating a .lisp file from the language .qi file. Qi is written in Qi. It creates a Lisp file from the version in the Qi language. We will call this qi.lisp.&lt;br /&gt;&lt;li&gt; Running the install.txt code on the new qi.lisp file. Qi has an "Install Qi" folder in the distribution where you should find a fresh CLISP exe and initialized memory file. It should also have the "Qi 6.2.txt" which corresponds to what I have called qi.lisp. It also has install.txt which is a lisp program that performs the following operations.&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; Makes a "qi" package&lt;br /&gt;&lt;li&gt; Loads the qi.lisp file and compiles it into memory.&lt;br /&gt;&lt;li&gt; Saves the memory as a new startup image.&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;li&gt; Finally, you can run lisp.exe -M with the new memory image that was created. You include the startup_qi.txt file to launch the qi read-print-eval loop.&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;So we understand the qi bootstrap process better now and we can see why things in our qi_startup.txt can be a bit wierd. Let us specify an argument loading version of qi_startup.txt&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(TERPRI)&lt;br /&gt;&lt;br /&gt;(DEFUN LOAD_N_LAUNCH (X)&lt;br /&gt;  (COND ((EQ X NIL) "Done Loading")&lt;br /&gt;        (T (qi::load (CAR X))&lt;br /&gt;           (LOAD_N_LAUNCH (CDR X)))))&lt;br /&gt;&lt;br /&gt;(qi::initialise_environment)&lt;br /&gt;(LOAD_N_LAUNCH EXT:*ARGS*)&lt;br /&gt;(qi::qi)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;All we have to do now is create a version of the qi.bat file that launches qi. It should simply run the lisp.exe with the lispinit.mem file that the Qi bootstrapper created and pass along any arguments it recieves. I personally like to have it be able to load from anywhere so I include the full path in the specification of the executable and the memory image.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;"D:\tools\Qi 6.2\lisp.exe" -M "D:\tools\Qi 6.2\lispinit.mem" "D:\tools\Qi 6.2\qi_launcher.txt" %1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course, when you are playing with your memory images, make sure to keep a backup around in case something goes awry. Now if you double click a .qi file (assuming you never tried before), will ask you to choose which program to run it with. Select the "Choose from a list" option, then select the&lt;br /&gt;"Browse" option and find your version of Qi.bat. Your program should launch and include all the wonderful functions you have defined. It makes debugging much easier in my opinion.&lt;br /&gt; &lt;br /&gt;Obviously, you could place whatever code you wanted in the load_n_launch spot.  Just call qi::qi to get into the main qi loop at the end of it and everything should work fine. But this brings us to the second issue, what about lisp functions we want to load? Unfortunately, we could not place them in the load_n_launch spot because QI already has changed many important things like case sensitivity and which characters count as "comments" among other things. If we try to load a lisp file, we will likely encounter errors. &lt;br /&gt;&lt;br /&gt;So how do we get CL-PPCRE into Qi? The easiest way is to include the entire package into our memory image. Once we have a lisp memory image with the functions included in it, we can then make a Qi image that will have access to the original functions. While the steps below work, they create monster images in terms of memory size. So be certain you only include the things you really need. Oh, and there are better ways of doing this but I don't know about them yet. Feel free to enlighten me.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Download the latest version of CLISP&lt;br /&gt;&lt;li&gt;Download the latest version of CL-PPCRE&lt;br /&gt;&lt;li&gt;Run CLISP and type (load "path\\to\\CL-PPCRE\\load.lisp") &lt;br /&gt;&lt;li&gt;Type (EXT:SAVEINITMEM) to save the lisp image. Then type (CD) if you don't know what directory it saved them in.&lt;br /&gt;&lt;li&gt;Copy the lispinit.mem and the contents of the CLISP/full directory, into your Install Qi directory.&lt;br /&gt;&lt;li&gt; Type lisp.exe -M lispinit.mem install.txt&lt;br /&gt;&lt;li&gt; Copy lisp.exe and lispinit.mem into the main Qi directory.&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;And that will give you a customised version of Qi! You can now perform wonders such as&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(1-) (CL-PPCRE:SCAN-TO-STRINGS "(a)*b" "xaaaab")&lt;br /&gt;"aaaab"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But remember, Qi only reads off one result at the top level. To see the rest of your results, you have to use multiple-value-list&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(2-) (MULTIPLE-VALUE-LIST (CL-PPCRE:SCAN-TO-STRINGS "(a)*b" "xaaaab") )&lt;br /&gt;["aaaab" #["a"]]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you have anything else you need to load, you can do it in the above manner.&lt;br /&gt;&lt;br /&gt;So in short, we can have our cake and eat it too. If you can get something working in CLISP, you should be able to get somethign working in Qi. I hope these tips help your Qi experience and let me know what you think!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-114633196124745473?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/114633196124745473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=114633196124745473' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114633196124745473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114633196124745473'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2006/04/building-lisp-qi-and-other-fun-hacks.html' title='Building Lisp, Qi and other Fun Hacks'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-114612494020050482</id><published>2006-04-27T01:00:00.000-07:00</published><updated>2006-05-01T00:32:23.260-07:00</updated><title type='text'>Qi Programming Basics: Where Guards and Backtracking</title><content type='html'>Qi Programming Basics: Where Guards and Backtracking.&lt;br /&gt;&lt;br /&gt;In Pattern Matching Basics, we learned about values that must match literals or named parameters. We also learned that this pattern matching can fail. We learned that on the right hand side, you can return a value when the left hand side matches. But what if we want to ensure our variable matches also meet some other specific conditions?&lt;br /&gt;&lt;br /&gt;Having covered the left hand side of the arrow operator, we can now cover the right hand side of the -&gt; operator, which deals with restricting function calls. The “where” allows us to call whatever function we want to and have it return only if said “where’ function returns true. If the where returns false, we continue down the function definitions until we find both a left hand pattern match, and a right hand “where” clause satisfaction. Let us take a simple example, greater-than-10&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define greater-than-10&lt;br /&gt;X -&gt; true where (&gt; X 10)&lt;br /&gt;_  -&gt; false&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(11-) (greater-than-10 20)&lt;br /&gt;true&lt;br /&gt;&lt;br /&gt;(12-) (greater-than-10 5)&lt;br /&gt;false&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Just as the pattern matching side acts as a sieve for the structure of the input, the where clause acts as functional sieve to ensure that the data matches certain parameters. It makes it easy to define recursive functions. Simply specify the basic cases first and the recursive cases after. The prime? function given in the Qi language book shows this behavior well and I’ll include it here&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define prime?&lt;br /&gt;X -&gt; (prime1? X (sqrt X) 2))&lt;br /&gt;&lt;br /&gt;(define prime1?&lt;br /&gt;  X Max Div   -&gt; true   where (&gt; Div Max)&lt;br /&gt;  X Max Div   -&gt; false where (integer? (/ X Div))              &lt;br /&gt;  X Max Div   -&gt; (prime1? X Max (+ 1 Div)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So prime calls prime1? setting X to the prime we want to test for, Max to the sqrt of X to limit the prime testing, and Div to 2. If the Div is greater than the Max, it returns true because obviously we have tested for primeness up to the sqrt of X. If it finds any integer divisors, the number is obviously non prime so it returns false. If we pass the first 2 where clauses, then we know we need to test another number so it adds 1 to Div and calls itself recursively and thus walks up to Div &gt; Max. This specifies the prime numbers and is easy to read, but inefficient.&lt;br /&gt;&lt;br /&gt;So now that we understand the simple basics of the where clause, we use them to implement some very interesting constructs. Qi provides some syntactic sugar to make writing these sorts of constructs easier, but we should remember that we are only truly dealing with the “where” clause fundamentally. We need to learn about a few new important operators and a new literal. First, we introduce the &lt;- notation that we use instead of -&gt; to signify that if the pattern on the left matches, and the function on the right does not fail, then we can return the result. We specify the idea of “failure” by the literal #\Escape, which is also known as the failure object. We will also introduce a form called “fail-if” that can help make these functions more readable and robust.&lt;br /&gt;&lt;br /&gt;Let us begin with a simple case of a binary tree of numbers built out of lists. We will use the empty list to signify a null tree. So we have structures like [L X R] where L and R are lists of that type or empty lists.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(62-) [[[[] 4 [] ] 2 [[] 5 []]] 1 [ [[] 6 []] 3 [ [] 7 []] ]]&lt;br /&gt;[[[[] 4 []] 2 [[] 5 []]] 1 [[[] 6 []] 3 [[] 7 []]]]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now let us use an old backtracking standby of the computer science world, DFS. DFS, for those who do not know, stands for Depth First Search. A DFS goes to the left hand side and right hand side while printing its way around the list. How it prints depends on if we have want a preorder DFS, an inorder DFS, or a postorder DFS. You can find more on the concept at the &lt;a href="http://en.wikipedia.org/wiki/Tree_search_algorithm"&gt; Wikipedia Tree Search Algorithm &lt;/a&gt; page. We can define a tree that looks like the tree on that page as follows. (Here we use the “set” function to set a symbol to the value of the list, to make things easier to read.)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(70-) (set *b-list* [ [[[] g []] h [[[] f []] i [[] e []]]] a [[] b [[[] d []] c []]] ] )&lt;br /&gt;[[[[] g []] h [[[] f []] i [[] e []]]] a [[] b [[[] d []] c []]]]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So how can we use the backtracking operator and the #\Escape symbol to implement this algorithm? First, we must note that we will need to return the #\Escape object for every result. This will ensure that our backtracking operations continue to happen even after we have matched something successfully and have “done” something (in this case print out an element). The basic case is when we have an empty node of only one element, for example [ [] 7 [] ]  should print 7 and return the failure object.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[[] X []]  -&gt; (do (output "~A " X) #\Escape)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That accomplishes that for us. It is also the base case so we can put it at the top of the function. Obviously, we don’t want it to backtrack, as it is the basic case, so we use the -&gt; operator to indicate that we wish to stop backtracking when this rule matches. But note that it does return the #\Escape element, as we don’t’ know where we are in the tree and we want any additional backtracking left on the stack to continue. The important point to remember is when a function returns something other than #\Escape, we halt the computation.&lt;br /&gt;&lt;br /&gt;What about the rest of the function? It depends on if we want preorder, inorder, or postorder printing of elements. We will start with the preorder case as we can follow the computation a bit more easily. It should print the first element, then print the left tree, then print the right tree. But at each of those operations, we want it to backtrack and continue on even after it has printed or displayed part of the tree for us. In this way, we can use the function stack as our “visit” stack. (Stacks are a requirement of DFS) By going back up the computational stack, we can find the next element that we should print. For Preorder we have&lt;br /&gt;&lt;br /&gt;[L X R]    &lt;- (do (output "~A " X) #\Escape)   [L X R]    &lt;- (dfs-pre L)   [L X R]    &lt;- (dfs-pre R)  So what this means is that it prints out the X, then returns #\Escape which fails. This causes us to backtrack to the next rule, the (dfs-pre L) rule. Note that this also uses the &lt;- operator, so when it finishes with an #\Escape (which is the only thing our function returns) we then can go to the (dfs-pre R) rule. But what happens when the (dfs-pre R) rule fails? We want another default case to return #\Escape for any computation that has gone this far.  _           -&gt; #\Escape&lt;br /&gt;&lt;br /&gt;Putting this together gives us the following definition.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define dfs-pre&lt;o:p&gt;&lt;/o:p&gt;&lt;span style=""&gt;&lt;br /&gt;&lt;/span&gt;  [[] X []]&lt;span style=""&gt;  &lt;/span&gt;-&gt; (do (output "~A " X) #\Escape)&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;span style=""&gt;  &lt;/span&gt;[L X R]&lt;span style=""&gt;    &lt;/span&gt;&lt;- (do (output "~A " X) #\Escape)&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;  &lt;/span&gt;[L X R]&lt;span style=""&gt;    &lt;/span&gt;&lt;- (dfs-pre L)&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;  &lt;/span&gt;[L X R]&lt;span style=""&gt;    &lt;/span&gt;&lt;- (dfs-pre R)&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;  &lt;/span&gt;_&lt;span style=""&gt;          &lt;/span&gt;-&gt; #\Escape&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;)&lt;/p&gt;  (86-) (dfs-pre (value *b-list*))&lt;br /&gt;a h g i f e b c d #\Escape&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The letters above are the results from the “output” function. The #\Escape is the end of our computation, as our function only returns #\Escape, we should not feel surprised to see it at the end of our output from the top level.&lt;br /&gt;&lt;br /&gt;We can accomplish post order by simply switching around the order that the function calls come in the list. Instead of printing first and backtracking to dfs L and dfs R, we can put the print at the end and come up with postorder.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define dfs-post&lt;br /&gt;[[] X []]  -&gt; (do (output "~A " X) #\Escape)&lt;br /&gt;[L X R]    &lt;- (dfs-post L)  &lt;br /&gt;[L X R]    &lt;- (dfs-post R)   &lt;br /&gt;[L X R]    &lt;- (do (output "~A " X) #\Escape)   &lt;br /&gt;_           -&gt; #\Escape&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(88-) (dfs-post (value *b-list*))&lt;br /&gt;g f e i h d c b a #\Escape&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And finally, we can define inorder as the following, by placing the print in between the L and R cases.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define dfs-in&lt;br /&gt;[[] X []]  -&gt; (do (output "~A " X) #\Escape)&lt;br /&gt;[L X R]    &lt;- (dfs-in L)  &lt;br /&gt;[L X R]    &lt;- (do (output "~A " X) #\Escape)   &lt;br /&gt;[L X R]    &lt;- (dfs-in R)   &lt;br /&gt;_           -&gt; #\Escape&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(89-) (dfs-in (value *b-list*))&lt;br /&gt;g h f i e a b d c #\Escape&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now if you input the following at the top level and run that program again, you will be able to see each of the inputs and watch how the #\Escape return values help move this backtracking along.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(91-) (track dfs-in)&lt;br /&gt;dfs-in&lt;br /&gt;&lt;br /&gt;(92-) (step +)&lt;br /&gt;True&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Long time computer science types will realize that this is a foolish way to handle DFS, and I would like to point out that I chose this method because walking trees is fairly well known and simply helps us learn. We can define a DFS inorder much easier by simply appending lists together. It takes no more lines in Qi than it does in Haskell.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define dfs-pre*&lt;br /&gt;[]      -&gt; []&lt;br /&gt;[L X R] -&gt; (append (append [X] (dfs-pre* L)) (dfs-pre* R)) )&lt;br /&gt;&lt;br /&gt;(95-) (dfs-pre* (value *b-list*))&lt;br /&gt;[a h g i f e b c d]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nicer, but not my point. *smile*&lt;br /&gt;&lt;br /&gt;Now perhaps we want to fail on a specific test of a result as opposed to using only the #\Escape operator to handle backtracking. Could our dfs function return true and still allow for backtracking? Fortunately, Qi provides us with a special form called “fail-if” that does exactly that. It takes in a function and a value. It tests to see if the value causes the function to return true. If it dose, it starts backtracking. If the test returns false, however, it stops backtracking. It basically means “backtrack if true”. Let us make a version of dfs-pre that uses these semantics.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define dfs-pre&lt;br /&gt;[[] X []]  -&gt; (do (output "~A " X) true)&lt;br /&gt;[L X R]    &lt;- (fail-if (/. Y Y) (do (output "~A " X) true))  &lt;br /&gt;[L X R]    &lt;- (fail-if (/. Y Y) (dfs-pre L))  &lt;br /&gt;[L X R]    &lt;- (fail-if (/. Y Y) (dfs-pre R))  &lt;br /&gt;_          -&gt; true&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(111-) (dfs-pre (value *b-list*))&lt;br /&gt;a h g i f e b c d true&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now after listing this form, try to see how the backtracking operator connects to the “where” clause described earlier. We have a test like in where. (/. Y Y), and we pass over clauses that do not match this test. All we are missing is a way to ensure that we don’t double up on the clauses. We want to return the clause AND test it in our where. Let us try a final rewrite of dfs-pre that uses only the usual -&gt; operators and the where. We would like it to look like.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define dfs-pre&lt;br /&gt;[[] X []]  -&gt; (do (output "~A " X) true)&lt;br /&gt;[L X R]    -&gt; (let Result (do (output "~A " X) true)&lt;br /&gt;              Result) where (not Result)&lt;br /&gt;[L X R]    -&gt; (let Result (dfs-pre L)&lt;br /&gt;              Result) where (not Result)&lt;br /&gt;[L X R]    -&gt; (let Result (dfs-pre R)&lt;br /&gt;              Result) where (not Result)&lt;br /&gt;_          -&gt; true&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However, you can see the Result variable goes out of scope at the end of the let and thus is not available to the where clause. If you tried to compile this you would get&lt;br /&gt;======&gt; Warning:&lt;br /&gt;the following variables are free in dfs-pre: Result;&lt;br /&gt;&lt;br /&gt;But you should remember that Qi deals with this internally and we can simply use the expressive power of the &lt;- and fail-if operators to handle our backtracking for us.&lt;br /&gt;&lt;br /&gt;Obviously, that serves as only the beginning of what we can accomplish with backtracking in Qi. In chapter 7 of the language book, we find a proplog based system that uses backtracking to build a backward chaining proof procedure. Hopefully, this guide should give you enough background on how the Qi where clause works so that you can fully understand the code in that chapter.&lt;br /&gt;&lt;br /&gt;I hope you enjoyed this little guide to the Qi where clause and backtracking in general. Using backtracking can greatly enhance the expressiveness of your program and provide a powerful syntax for dealing with recursion and non-determinism.  Please let me know any questions or comments that you have!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-114612494020050482?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/114612494020050482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=114612494020050482' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114612494020050482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114612494020050482'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2006/04/qi-programming-basics-where-guards-and.html' title='Qi Programming Basics: Where Guards and Backtracking'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-114577693906232730</id><published>2006-04-23T00:20:00.000-07:00</published><updated>2006-04-23T04:16:54.353-07:00</updated><title type='text'>Qi Programming Basics: Pattern Matching</title><content type='html'>The Qi language has the ability to create functions that return different results depending on the inputs. In most languages besides Haskell, ML, and Prolog, you must simply specify inputs and then test each input to determine what you want the function to return. This ends up cluttering the function definition with many “if” or “case” statements. This in turn lowers the readability and writeability of the language in question. Advanced functional languages take advantage of a special syntax that allows the definition of the return value based on the inputs to the function.&lt;br /&gt;&lt;br /&gt;A second, and more important, use for pattern matching is for binding the formal parameters of the function. In many languages, if you wish to extract different parts of the parameters in a function, you have to define local variables to hold the parts that you are interested in. In Qi, you use the pattern matching operator to do the special assignment for your cases up front. This simplifies the programming and makes the program more readable (and hence maintainable).&lt;br /&gt;&lt;br /&gt;Qi provides 2 special operators for the purposes of parameter pattern matching. The -&gt; operator is equivalent to the = operator in Haskell. It specifies that a pattern matched to the left of the arrow will produce the results specified on the right of the arrow, after rewriting the function on the right to use the values matched on the left. The other operator is _ and it basically tells the rewriter to “throw away” the input. Thus the Qi pattern matching system corresponds to what computer scientists call a priority rewrite system.&lt;br /&gt;&lt;br /&gt;Now that we have dispensed with some dense technical verbiage, let us look at what all of this actually means to a Qi programmer. We will start with the first meaning of pattern matching, namely matching basic elements with no bound formal parameters (i.e. none of what you would call “variables”). We will take 3 animals, jane, chuck, and rex and make a function called likes_to_eat that lets us know that jane likes pizza, chuck like cereal, and rex likes dog_food.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define likes_to_eat&lt;br /&gt; jane   -&gt;  pizza&lt;br /&gt; chuck  -&gt;  cereal&lt;br /&gt; rex    -&gt;  dog_food&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(11-) (likes_to_eat jane)&lt;br /&gt;pizza&lt;br /&gt;&lt;br /&gt;(12-) (likes_to_eat rex)&lt;br /&gt;dog_food&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Seems simple enough, no? So now lets see what our function has to say about what bob likes to eat.&lt;br /&gt;&lt;br /&gt;(13-) (likes_to_eat bob)&lt;br /&gt;error: partial function likes_to_eat;&lt;br /&gt;&lt;br /&gt;It produces an error as expected as we have not defined what bob likes in the above function. The error message could perhaps be more useful, but it does point us to the problem. Qi will also then ask if we want to “track” the function. This is Qi’s way of helping us find where we went wrong in our function call. If you say yes, Qi will display a lot of diagnostic messages when it encounters the likes_to_eat function so you can determine what went wrong.&lt;br /&gt;&lt;br /&gt;So let us modify our function to return the symbol “unknown” whenever we don’t know the animal that the function was called with. We use the _ operator to tell the system that we don’t care about the input, we just want to return unknown if we reach the pattern.&lt;br /&gt;&lt;br /&gt;(define likes_to_eat&lt;br /&gt; jane   -&gt;  pizza&lt;br /&gt; chuck  -&gt;  cereal&lt;br /&gt; rex    -&gt;  dog_food&lt;br /&gt; _      -&gt;  unknown&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;Running this version gives us the following output.&lt;br /&gt;&lt;br /&gt;(21-) (likes_to_eat bob)&lt;br /&gt;unknown&lt;br /&gt;&lt;br /&gt;Note the difference between this version and the following&lt;br /&gt;&lt;br /&gt;(define likes_to_eat&lt;br /&gt; _      -&gt;  unknown&lt;br /&gt; jane   -&gt;  pizza&lt;br /&gt; chuck  -&gt;  cereal&lt;br /&gt; rex    -&gt;  dog_food&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(23-) (likes_to_eat jane)&lt;br /&gt;unknown&lt;br /&gt;&lt;br /&gt;The pattern matches from top to bottom. Thus the _ operator matches anything input and returns unknown as a result, even though we have specified jane later on in the function. This is only the beginning of how tricky these sorts of rewrite rules can be, but as long as you remain aware of the order of evaluation, you should have relatively few problems with them.&lt;br /&gt;&lt;br /&gt;While returning “unknown” is OK, we may want a more useful error message. We now want to modify our function likes_to_eat to display a helpful error message that tells us WHAT caused the function to fail. We also want to stop the computation at this point. Qi provides a helpful function called “error” that stops the program and returns a string. We will make the string say “likes_to_eat has not heard of bob” if we input bob.&lt;br /&gt;&lt;br /&gt;To make the program work as we described, we want to return the following function (error "likes_to_eat has not heard of ~A" bob). Of course, you can immediately see that bob is a variable that we will need to input into the error function. This allows us to introduce the concept of formal parameters. In Qi, formal parameters start with an upper case letter. For simplicities sake, let us call the variable which will bind to bob X. Now our result becomes (error "likes_to_eat has not heard of ~A" X) where X is bound to bob. The Qi syntax makes this rule easy to write, just put X on the left of the arrow. We thus create a new definition of likes_to_eat.&lt;br /&gt;&lt;br /&gt;(define likes_to_eat&lt;br /&gt; jane   -&gt;  pizza&lt;br /&gt; chuck  -&gt;  cereal&lt;br /&gt; rex    -&gt;  dog_food&lt;br /&gt; X      -&gt;  (error "likes_to_eat has not heard of ~A" X)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(26-) (likes_to_eat bob)&lt;br /&gt;error: likes_to_eat has not heard of bob&lt;br /&gt;&lt;br /&gt;Now let us take a look at a more complicate pattern matching question. In Qi, we can use any of the special constructor forms on the left hand side of the arrow operator. These forms are “list”, “cons”, and “@p”. We can also use the “|” operator inside a list to extract the cons form. I recommend reading the Qi Language book to better understand these forms, but a simple exercise should suffice to show any programmer versed in list processing how they operate.&lt;br /&gt;&lt;br /&gt;(43-) (list a b c)&lt;br /&gt;[a b c]&lt;br /&gt;&lt;br /&gt;(44-) [ a b c ]&lt;br /&gt;[a b c]&lt;br /&gt;&lt;br /&gt;(45-) (cons a (cons b (cons c [])))&lt;br /&gt;[a b c]&lt;br /&gt;&lt;br /&gt;(46-) (@p 1 2)&lt;br /&gt;(@p 1 2)&lt;br /&gt;&lt;br /&gt;(47-) [ a b | c]&lt;br /&gt;[a b . c]&lt;br /&gt;&lt;br /&gt;(48-) [ a | b c]&lt;br /&gt;error: Improper use of |&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(48-) [ a | [b c] ]&lt;br /&gt;[a b c]&lt;br /&gt;&lt;br /&gt;Let us create an analog of the Haskell take function that takes N arguments from a list and returns the elements extracted. Defining it recursively, we find that if N is 0, then return [] or if the list is [] for any N, return []. Finally, return the application of take to itself by making a list of the head elements and the tail elements being the results of take N – 1.&lt;br /&gt;&lt;br /&gt;(define take-alpha&lt;br /&gt; 0  _  -&gt; []&lt;br /&gt; _  [] -&gt; []&lt;br /&gt; N  [X | XS] -&gt; [ X | (take-alpha (- N 1) XS) ] )&lt;br /&gt;&lt;br /&gt;For the first 2 patterns, we can easily see what the patterns match to. For the final pattern, we find that we get a number N and something called [ X | XS ]. This form means that X is the single element head of the list and XS is the remainder of the list. Each call to take-alpha reduces the number of elements in the list by one and reduces the N by one.&lt;br /&gt;&lt;br /&gt;(50-) (take-alpha 2 [ a b c])&lt;br /&gt;[a b]&lt;br /&gt;&lt;br /&gt;The first 2 patterns work slightly differently than Haskell programmers may be used to. To show this, let us define a function take-beta that reverses the first 2 rules.&lt;br /&gt;&lt;br /&gt;(define take-beta&lt;br /&gt; _  [] -&gt; []&lt;br /&gt; 0  _  -&gt; []&lt;br /&gt; N  [X | XS] -&gt; [ X | (take-beta (- N 1) XS) ] )&lt;br /&gt;&lt;br /&gt;(51-) (take-alpha 0 bad_thing)&lt;br /&gt;[]&lt;br /&gt;&lt;br /&gt;(52-) (take-beta 0 bad_thing)&lt;br /&gt;[]&lt;br /&gt;&lt;br /&gt;(53-) (take-alpha bad_thing [])&lt;br /&gt;[]&lt;br /&gt;&lt;br /&gt;(54-) (take-beta bad_thing [])&lt;br /&gt;[]&lt;br /&gt;&lt;br /&gt;This differs from Haskell in that Haskell would return the bottom operator for the middle 2 elements because it could not match bad_thing to the list or the number respectively. The typesafe version of Qi would throw an error at compile time if we attempted such a call. In that case, Qi provides a default symbol called #\Escape that works along the lines of the Haskell bottom operator (with significant differences not described here). Regardless, we can see that the notion of “more defined” that we find in Haskell does not apply to the general version of Qi.&lt;br /&gt;&lt;br /&gt;You can make the left hand side of the equation as complicated as you wish. We will create a list that has alternating types, the first being a number and the second being a tuple created by the @p operator. For example, we would like the function to make [ 1 (@p 3 4) 5 (@p 8 5)] add up to 26. We want it to be able to do it for any valid list length. The definition follows.&lt;br /&gt;&lt;br /&gt;(define complicated-list-add&lt;br /&gt;[] -&gt; 0&lt;br /&gt;[ X | [ (@p Y Z) | XS]] -&gt; (+ (+ X (+ Y Z)) (complicated-list-add XS))&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;Testing this function gives&lt;br /&gt;&lt;br /&gt;(58-) (complicated-list-add [ 1 (@p 3 4) ])&lt;br /&gt;8&lt;br /&gt;&lt;br /&gt;(59-) (complicated-list-add [ 1 (@p 3 4) 5 (@p 8 5)])&lt;br /&gt;26&lt;br /&gt;&lt;br /&gt;If we try to simply input 3 numbers we get the following error.&lt;br /&gt;&lt;br /&gt;(60-) (complicated-list-add [ 1 2 3])&lt;br /&gt;error: partial function complicated-list-add;&lt;br /&gt;&lt;br /&gt;The pattern matcher could not match 2 to (@p X Y) so it returns the same error we saw when we tried to call likes_to_eat with bob. It doesn’t know how to apply it and it gives us an error. If we wished, we could add error handling in the same manner as likes_to_eat.&lt;br /&gt;&lt;br /&gt;One final point remains on the basics of pattern matching in Qi. What happens if we have a variable that we didn’t specify on the left hand side of the arrow? The rewrite rule described above wouldn’t know how to decipher it as we didn’t explicitly define it. Qi has chosen the route of warning the user but defining the function as opposed to generating an error. We can see the behavior below.&lt;br /&gt;&lt;br /&gt;(define bad-rewrite&lt;br /&gt;X -&gt; Y)&lt;br /&gt;&lt;br /&gt;======&gt; Warning:&lt;br /&gt;the following variables are free in bad-rewrite: Y;&lt;br /&gt;&lt;br /&gt;bad-rewrite&lt;br /&gt;&lt;br /&gt;(62-) (bad-rewrite 10)&lt;br /&gt;Y&lt;br /&gt;&lt;br /&gt;If you are a Lisp programmer, you may worry about variable capture due to this rewrite rule. Fortunately, Qi handles this case for us via the rewrite system and we don’t have to worry about it in this case. This also means we can return proper names from functions in the relatively few cases where we want to do this. But expressive power always means we need to take care of how we code things, thus the reason for the warning.&lt;br /&gt;&lt;br /&gt;(63-) ((/. Y (bad-rewrite Y)) 12)&lt;br /&gt;Y&lt;br /&gt;&lt;br /&gt;Whew. Congrats to all that made it to the bottom of this pedantic look at the Qi pattern matching system. You should note that this only covers rewrite rules without guards (the Qi “where” special form). If you delve further into Qi, you will find that the combination of the arrow and where can allow native backtracking of the functions that you call. Yes, I said native backtracking of function calls! More on that later.&lt;br /&gt;&lt;br /&gt;Enjoy your Qi!&lt;br /&gt;&lt;br /&gt;PS: Mark Tarver, the main implementer of Qi, had this to say about the warn vs error issue with Qi variables.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The main motivation for this is to allow users to mix&lt;br /&gt;Lisp code into Qi code.  Since Lisp reverts to the&lt;br /&gt;uppercase when case sensitivity is invoked (Qi is&lt;br /&gt;case sensitive), if you want to mix Lisp into Qi you have to violate&lt;br /&gt;the free variable condition.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;(0-)  (define implode&lt;br /&gt;   Chars -&gt; (COERCE Chars STRING))&lt;br /&gt;======&gt; Warning:&lt;br /&gt;the following variables are free in implode: COERCE; STRING;&lt;br /&gt;implode&lt;br /&gt;&lt;/p&gt;&lt;p&gt;(1-) (implode [#\a #\b #\c])&lt;br /&gt;"abc"&lt;br /&gt;&lt;/p&gt;&lt;p&gt;You see the idea, that is why you get a warning and&lt;br /&gt;not an error.  Being able to mix the two is a big plus.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;However if you really want to block off functions like&lt;br /&gt;bad-rewrite then (strong-warning +) will do it and you&lt;br /&gt;get an error and not a warning.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;(3-) (strong-warning +)&lt;br /&gt;true&lt;br /&gt;&lt;/p&gt;&lt;p&gt;(4-) !0&lt;br /&gt;&lt;/p&gt;&lt;p&gt;0.&lt;br /&gt;(define implode&lt;br /&gt;   Chars -&gt; (COERCE Chars STRING))&lt;br /&gt;error: the following variables are free in implode: COERCE; STRING;&lt;br /&gt;&lt;/p&gt;Mark&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-114577693906232730?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/114577693906232730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=114577693906232730' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114577693906232730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114577693906232730'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2006/04/qi-programming-basics-pattern-matching.html' title='Qi Programming Basics: Pattern Matching'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-114562584117566567</id><published>2006-04-21T06:23:00.000-07:00</published><updated>2006-04-21T07:08:47.703-07:00</updated><title type='text'>Qi and the "Magic" Prime Type</title><content type='html'>&lt;span style="font-family:arial;"&gt;The Qi type system allows for some very interesting types not typically &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt; available to non-FOL type systems. To better understand what you can do &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt; with this system, I have made a simple and naive prime type to show off &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt; the power of the Qi types. The idea behind it seems very simple, namely &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt; we make a number subtype that matches only primes. Then, we can define &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt; functions that take only prime numbers and we can be certain that only &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt; prime numbers can get into this function. &lt;/span&gt;&lt;br /&gt;&lt;p style="font-family: arial;"&gt;To begin this process, we need to have a function that determines&lt;br /&gt;primes. Taking the very simple approach to generating primes used in&lt;br /&gt;the book, we create a prime? function with the following definition.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(define prime?&lt;br /&gt; { number --&gt; boolean }&lt;br /&gt; X -&gt; (prime*? X (round (sqrt X)) 2))&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(define prime*?&lt;br /&gt;   { number --&gt; number --&gt; number --&gt; boolean }&lt;br /&gt;   X Max Div -&gt; true   where (&gt; Div Max)&lt;br /&gt;   X Max Div -&gt; false where (integer? (/ X Div))&lt;br /&gt;   X Max Div -&gt; (prime*? X Max (+ 1 Div))&lt;br /&gt;)&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;Next, we need to have a type function that tells the compiler that our&lt;br /&gt;prime type is a subtype of numbers. Anyplace we can use a number, ie in&lt;br /&gt;+ or any other math function, we want to be able to use primes. The Qi&lt;br /&gt;Language book describes this type and we will use the pattern described&lt;br /&gt;in the book. As an aside, this ends up being so useful that future&lt;br /&gt;versions of Qi may just need to include this type natively.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(datatype subtype&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;  (subtype B A); X : B;&lt;br /&gt; _____________________&lt;br /&gt; X : A;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;  _____________________&lt;br /&gt; (subtype prime number);&lt;br /&gt;)&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;Finally, we now can make our prime type by using the following&lt;br /&gt;definition. Note that this definition is incomplete and try to&lt;br /&gt;understand why it does not allow us to define a function that takes a&lt;br /&gt;number and returns a prime. However, this function should allow us to&lt;br /&gt;find primes at the top level (and hence in loaded files as well). We&lt;br /&gt;will expand on the definition below. Basically, the function should say&lt;br /&gt;that if we have a number and it passes the prime? function, then we&lt;br /&gt;should consider it a prime.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(datatype prime&lt;br /&gt; if(and (number? X) (prime? X))&lt;br /&gt; _________&lt;br /&gt; X : prime;&lt;br /&gt;)&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;Now that we have an incomplete definition, let us see it in use.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(2+) 3 : prime&lt;br /&gt;3 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(3+) 4 : prime&lt;br /&gt;error: type error&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(4+) 5 : prime&lt;br /&gt;5 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(5+) 6 : prime&lt;br /&gt;error: type error&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(6+) 8 : prime&lt;br /&gt;error: type error&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(7+) 9 : prime&lt;br /&gt;error: type error&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(8+) 11 : prime&lt;br /&gt;11 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(9+) 13 : prime&lt;br /&gt;13 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;That's a smart type! *grin*&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;To understand why this function does not complete our definition of&lt;br /&gt;prime, we should try to build a function that takes in a prime and&lt;br /&gt;finds the next prime on the number line. Let us call it next-prime. It&lt;br /&gt;should take a prime and find the next prime in the number line by&lt;br /&gt;stepping up the number line by one and testing for prime-ness.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(define next-prime&lt;br /&gt;  { prime --&gt; prime }&lt;br /&gt; X -&gt; (next-prime* (+ 1 X))&lt;br /&gt;)&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(define next-prime*&lt;br /&gt; { number --&gt; prime }&lt;br /&gt; X -&gt; X where (prime? X)&lt;br /&gt; X -&gt; (next-prime* (+ 1 X))&lt;br /&gt;)&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;However, if we try to compile the code up to this point, we find that&lt;br /&gt;we get the following not-so-helpful error message.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;Correctness Check Failure; rule 1 of next-prime*&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;Why does this happen? Obviously, the type system cannot prove that X-&gt;&lt;br /&gt;X is a prime where (prime? X). While in the non-typesafe version of Qi,&lt;br /&gt;this function does indeed perform as requested. But because the type&lt;br /&gt;checker cannot prove that it will output ONLY primes, it cannot&lt;br /&gt;typecheck our program. To make our function work, we have to let the&lt;br /&gt;typechecker understand that if a number passes (prime? X) then it&lt;br /&gt;definitely is a prime.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;Fortunately for us, Qi provides a mechanism that can check the guards&lt;br /&gt;and give a type depending on if a guard passes. Qi has a special type&lt;br /&gt;for guards called "verified" that only matches when the guard itself&lt;br /&gt;returns true. The guard obviously runs at runtime but Qi can use the&lt;br /&gt;verified to ensure that we have correct types even at compile time. Our&lt;br /&gt;assumption is that if (prime? X) is "verified" then X is a prime. In Qi&lt;br /&gt;notation we then have the new prime type as follows.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(datatype prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;  if(and (number? X) (prime? X))&lt;br /&gt; _________&lt;br /&gt; X : prime;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;  ____________________&lt;br /&gt; (prime? X) : verified &gt;&gt; X : prime;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;)&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;We now have a complete (but very inefficient) version of the class of&lt;br /&gt;numbers we know as primes as a native Qi type. No non-prime will ever&lt;br /&gt;typecheck to the type prime even during runtime or after mathematical&lt;br /&gt;manipulation. Let us try it out.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(2+) (next-prime 5)&lt;br /&gt;7 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(3+) (next-prime 7)&lt;br /&gt;11 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(4+) (next-prime 101)&lt;br /&gt;103 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(5+) (next-prime 103)&lt;br /&gt;107 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(6+) (next-prime 107)&lt;br /&gt;109 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(7+) (next-prime 109)&lt;br /&gt;113 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(8+) (next-prime 113)&lt;br /&gt;127 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(9+) (next-prime 4)&lt;br /&gt;error: type error&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;(10+) (next-prime* 4)&lt;br /&gt;5 : prime&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;A good follow up exercise would be to take the stream datatype defined&lt;br /&gt;in the Qi Language book and make a stream of primes with these&lt;br /&gt;functions. Also, you could extend the type to use a new prime? function&lt;br /&gt;that implements a wheel sieve to ensure much faster testing for primes.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;As a final question, is there any way to rid ourselves of the number?&lt;br /&gt;test inside of primes? I've tried using sequents, subtypes, and a&lt;br /&gt;host of other methods but it always causes the program to crash on&lt;br /&gt;typechecking with  sec.SQRT: &amp;&amp;amp;X is not a NUMBER.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;Hope you enjoyed my little prime type and happy hacking!&lt;br /&gt;&lt;/p&gt;&lt;span style="font-family:arial;"&gt;--- &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt; EntropyFails  &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-114562584117566567?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/114562584117566567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=114562584117566567' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114562584117566567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114562584117566567'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2006/04/qi-and-magic-prime-type.html' title='Qi and the &quot;Magic&quot; Prime Type'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26662278.post-114562564103286722</id><published>2006-04-21T05:44:00.000-07:00</published><updated>2006-04-21T18:32:53.223-07:00</updated><title type='text'>Welcome to Programming Kung Fu Qi</title><content type='html'>&lt;p style="font-family: arial;"&gt;The Qi Programming language extends Common Lisp to provide complete First Order Logic types, function guards, and pattern matching. When you program it, it feels a bit like Lisp and a bit like Haskell. It has native and pure lambda expressions which means you get all the wonders of currying, partial application, and continuations with none of the Monads. You get all this and more for the low, low price of GPL.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;Welcome to the Programming Kung Fu Qi blog. I’ll be posting about whatever I can learn of this language and hopefully we can develop a community of people interested in finding out what Qi offers to the computer science world.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;Get your hack on by downloading Qi at...&lt;/p&gt;&lt;p style="font-family: arial;"&gt;&lt;a href="http://www.lambdassociates.org/"&gt;http://www.lambdassociates.org/&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: arial;"&gt;Then hop on the Qi discussion board at...&lt;/p&gt;&lt;a style="font-family: arial;" href="http://groups.google.com/group/Qilang"&gt; http://groups.google.com/group/Qilang&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Enjoy!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/26662278-114562564103286722?l=programmingkungfuqi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmingkungfuqi.blogspot.com/feeds/114562564103286722/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26662278&amp;postID=114562564103286722' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114562564103286722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26662278/posts/default/114562564103286722'/><link rel='alternate' type='text/html' href='http://programmingkungfuqi.blogspot.com/2006/04/welcome-to-programming-kung-fu-qi.html' title='Welcome to Programming Kung Fu Qi'/><author><name>EntropyFails</name><uri>http://www.blogger.com/profile/10583617029739151930</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
