<?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-3916802132854520262</id><updated>2011-09-30T07:15:05.905-05:00</updated><category term='chat'/><category term='feedgetter'/><category term='release'/><category term='game demo'/><category term='allcombinations'/><category term='plugins'/><category term='python'/><category term='gripes'/><category term='haskell_synth'/><category term='rant'/><category term='haskell'/><category term='gnash'/><title type='text'>Ill Logic Tech</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3916802132854520262.post-3536241765003634438</id><published>2011-07-16T20:42:00.036-05:00</published><updated>2011-07-17T15:25:35.222-05:00</updated><title type='text'>Haskell - Can your language's type system do this?</title><content type='html'>&lt;div style="background-color: transparent; margin-top: 0px; margin-left: 0px; margin-bottom: 0px; margin-right: 0px; font-family: 'Times New Roman'; "&gt;&lt;span id="internal-source-marker_0.8556585891637951" style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Haskell is known for its very strict, and yet very versatile type system. There's so much to learn about it, and I'm barely scratching the surface myself. But I've thought of a simple example of something impressive that I think people who know nothing about the language could still appreciate, and hopefully it will convince you to check it out.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Note: There is something in Haskell called "Type level programming". I'll leave you to look it up and decide whether what I'm doing here is an example of this or not. I never figured that out. but what I'm about to show you is at very least something you probably can't do in your language, unless your language is even cooler than Haskell.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Let's start with this simple program:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; font-size:10pt; " &gt;data Purse a b c = Purse a b c&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" &gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; font-size:10pt;" &gt;data Keys = Keys&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; font-size:10pt; " &gt;data Phone = BlackBerry | IPhone | Android&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; font-size:10pt; " &gt;data Wallet = LeatherWallet Float | MoneyClip Float&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" &gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; font-size:10pt; "&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;  font-size:10pt;" &gt;addKeys (Purse ( ) b c) newkeys = Purse newkeys b c&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;  font-size:10pt;" &gt;addPhone (Purse a ( ) c ) newphone = Purse a newphone c&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; font-size:10pt; " &gt;addWallet (Purse a b ( )) newwallet = Purse a b newwallet&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" &gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; font-size:10pt; "&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; font-size:10pt; " &gt;emptyPurse = Purse ( ) ( ) ( )&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" &gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;font-size:10pt;  "&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;font-size:10pt;  " &gt;leaveHouse :: (Purse Keys Phone Wallet) -&amp;gt; ( )&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;font-size:10pt;  " &gt;leaveHouse purse = ( )&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;font-size:10pt;  " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;In short, this program makes sure that you add your keys, a phone, and a wallet to your purse before you leave the house. However, unlike most languages, your compiler will make you do this, rather than the runtime.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;So first, let me decipher this thing for you.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size:10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;data Purse a b c = Purse a b c&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;This creates a data type called &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. It is a parametric data type, meaning that it takes other types as parameters, in this case 3 different ones. This is very similar to Java or C++, with something like &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Vector&amp;lt int &amp;gt&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;a&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;b&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, and &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;c&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; can be anything, at least for now. On the right side of the equal sign, we describe what it requires to construct an object of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. This also takes three parameters, however these parameters are values, not types, but the values must be of types &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;a,&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;b&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; and &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;c &lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;respectively. (Note that in Haskell, it's fairly common for the type, and the value of the type, to have the same name. It might seem confusing, but if you understand the context they're each used in, it's unambiguous which is meant. So here, on the left, &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; is the type, but on the right, &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse a b c&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; represents the value, or more properly one would say that on the right &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; is the type constructor)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;This is basically like a &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;struct&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; in C. So in all, we have something like a templated struct in C++, with one data member of each parametric type. For example, based on this declaration, you could create a variable of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse Int Float Int &lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;that had the value &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse 1 2.3 4&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; or &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse 2 5.7 8&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. You could also (in the same program) create a variable of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse Int Char Char&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, and it could hold the value &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse 5 'a' '%'&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; .&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;data Keys = Keys&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;data Phone = BlackBerry | IPhone | Android&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;data Wallet = LeatherWallet Float | MoneyClip Float&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Phone&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; and &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Wallet&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; are also datatypes. They are not parametric, however they have a different feature. The variables of these types can each take on multiple forms. A Phone variable can either have the value &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;BlackBerry&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;IPhone&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, or &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Android&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. Very similar to an &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;enum&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; in C, they basically are constants, and variables of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Phone&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; are restricted to them. &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Wallet&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; however, is a bit different. In addition to having multiple forms, it also has a Float parameter. If you remember &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; variables had parameters of unspecified types, however in this case we specify that it must be a &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Float&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Keys&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; is simplest of all, it can only have one value, Keys, with no parameters.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;addKeys (Purse ( ) b c) newkeys = Purse newkeys b c&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;This is a function definition. It takes two parameters. Similar to &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;def addKeys(purse, newkeys):&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; in Python. However, Haskell uses something called pattern matching. You can find this in Erlang, and I'm sure a good handful of other languages as well. What this generally does is allow you to define a function multiple times, for different input, as long as every definition has the same type signature. However in this case we're only doing one, because we just want to use it to (partially) define the type signature. The first parameter of the &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; object has to be &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, which is of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. This is in some ways like &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;None&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; or &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;NULL &lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;in other languages, however it's its own type, with only one value. Variables &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;a&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; and &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;b&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; can be any value of any type. What it returns is a new &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, with &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;newkeys&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; as its first parameter, rather than &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. The other parameters depend on what's passed in.This also means that the new &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; has a different type than the first one: &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse Keys b c&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, rather than &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse ( ) b c&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Similar in Python would be:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;def addKeys(purse, newkeys):&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; text-indent: 0.5499999999999972pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;if purse.a == None:&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;newpurse = copy(purse)&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;newpurse.a = newkeys&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;return newpurse&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;The difference being that the Haskell version restricts the type of purse, the consequences of which we'll see in a bit.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;addPhone (Purse a ( ) c ) newphone = Purse a newphone c&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;addWallet (Purse a b ( )) newwallet = Purse a b newwallet&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Exactly the same as &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;addKeys&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, except that &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; are in different slots, appropriate to where this new phone or wallet should go. Again, note that the type of purse returned is different than then one entered, and that the type entered is partially parametric. For instance, for &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;addPhone&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;c&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; can either be of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Wallet &lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;or of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; . Actually, again it could really be of any type, but if the purse was created with the functions defined in this program, it would be one of those.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;emptyPurse = Purse ( ) ( ) ( )&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;This is defining a value called &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;emptyPurse&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. It is a Purse of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse ( ) ( ) ( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; and of value &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse ( ) ( ) ( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; .&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;leaveHouse :: (Purse Keys Phone Wallet) -&amp;gt; ( )&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;leaveHouse purse = ( )&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Finally, we have a function with an explicit type signature. Until now we've been taking advantage of type inference. However, here we want to force &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;leaveHouse &lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;to have a specific type signature. The one argument to this function is of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse Keys Phone Wallet&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. Basically, any wallet with everything in it. No &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. The return value of this function happens to be &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; , but this is only because this is for demonstration. For our purposes, we don't care what it returns.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Ok cool, so what's the point? Well let's fire up the interpreter, ghci:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;Prelude&amp;gt; :l purse.hs&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;[1 of 1] Compiling Main ( purse.hs, interpreted )&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;Ok, modules loaded: Main.&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; let p1 = emptyPurse&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; let p2 = addKeys p1 Keys&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; let p3 = addWallet p2 (LeatherWallet 50.24)&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; let p4 = addPhone p3 BlackBerry&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; leaveHouse p4&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;( )&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Cool, we've left the house successfully. Let's inspect the types of each purse:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; :t p1&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;p1 :: Purse ( ) ( ) ( )&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; :t p2&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;p2 :: Purse Keys ( ) ( )&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; :t p3&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;p3 :: Purse Keys ( ) Wallet&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; :t p4&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;p4 :: Purse Keys Phone Wallet&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Remember, these aren't the values, these are the types.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Now let's restart out interpreter, and try to skip a step:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;Prelude&amp;gt; :l purse.hs&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;[1 of 1] Compiling Main ( purse.hs, interpreted )&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;Ok, modules loaded: Main.&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; let p1 = emptyPurse&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; let p2 = addWallet p1 (MoneyClip 5.20)&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; let p3 = addKeys p2 Keys&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; leaveHouse p3&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" &gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&amp;ltinteractive&amp;gt:1:11:&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;    Couldn't match expected type `Phone' against inferred type `()'&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;      Expected type: Purse Keys Phone Wallet&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;      Inferred type: Purse Keys () Wallet&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;    In the first argument of `leaveHouse', namely `p3'&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;    In the expression: leaveHouse p3&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; p4 = addKeys p3 Keys&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;We now have an error, because it was expecting a purse without &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; anywhere in its type parameters. Remember, it's not complaining about a bad value, this pass doesn't know about the value, because this is a compiler error. It's complaining about the type. This doesn't look too different from something you might set up in Python, but remember, with Haskell, if you put these lines into a program, you would get these errors without having to run it (you wouldn't even be able to).&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Now for fun, with the same interpreter session, let's try making a new purse, adding the keys to p3 a second time:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;*Main&amp;gt; let p4 = addKeys p3 Keys&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" &gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&amp;ltinteractive&amp;gt:1:17:&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;    Couldn't match expected type `()' against inferred type `Keys'&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;      Expected type: Purse () t t1&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;      Inferred type: Purse Keys () Wallet&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;    In the first argument of `addKeys', namely `p3'&lt;/span&gt;&lt;/p&gt;&lt;p dir="ltr" style="margin-left: 35.45pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;    In the expression: addKeys p3 Keys&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;It's expecting a Purse with the first parameter of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;( )&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;. Any Purse that has &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;addKeys&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; in its "history" will not have this in its type, it will be of type &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Keys&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, so the compiler will not let you call &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;addKeys&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; again.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Now, remember one particularly interesting thing here: when desiging the &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;addKeys&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;addWallet&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;, and &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;addPhone&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; functions, we did not know exactly what type of &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Purse &lt;/span&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;would be going into them. We just set one restriction, that one particular slot had to be empty. The actual types of purse going into the functions were realized by what called the functions.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;Why would you want to do something like this? Supposing you were creating a library function to call on some sort of API. You want to allow for multiple function calls to initialize some sort of object before kicking it off to the library. In a language like C or Python, failure to set some sort of initialization variable would lead to a runtime error you have to decipher. Here, the compiler won't let you run the program until you to set all of the necessary parameters, and you can set them in any order*. There's a benefit to having things fail before you even have a chance to run them. It's a pain to get working,  but once it does, your program will have far fewer errors.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;This trick I've described to you, however confusing I made it sound, is based on the very basics of the Haskell type system. There's a whole crazy world out there. It's complicated, but once you get to know it, you can force yourself into some pretty stable programs.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: transparent;"&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; " &gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt; font-family: 'Times New Roman'; color: #ABC; background-color: transparent; font-weight: normal; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;* Actually, the way I have it set up, while you can run these functions in any order, it (for better or for worse) forces you to call the functions in the same order every time you use them, if you ever use it more than once in the same program. However, using more advanced features (typeclasses) I think it would be possible to overcome this, though I've not tried it.&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-3536241765003634438?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/3536241765003634438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=3536241765003634438' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/3536241765003634438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/3536241765003634438'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2011/07/haskell-can-your-languages-type-system.html' title='Haskell - Can your language&apos;s type system do this?'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3916802132854520262.post-1669457924176050154</id><published>2011-04-29T11:53:00.008-05:00</published><updated>2011-04-29T13:41:33.441-05:00</updated><title type='text'>Lower the Barrier for Scratching Open Source Itches!</title><content type='html'>Ok, this is an idea I've had for some time now, I think it's time to put it out there and see what a large audience thinks. I'm a bit ignorant about how distributions are set up, maybe it's just impractical for some reason I'm unaware of.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think there should be an easy way for users of a distro to jump right into development. This stuff is done for free, we need all the help we can get. It would help to eliminate any barriers to entry we can. My proposal is that it should be integrated into the package manager.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is the process I envision: I, the user with coding skills, have an itch with Program X. I issue one command, let's say "sudo apt-get --collab programx&lt;packagename&gt;". Here's what it does:&lt;/packagename&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;It automatically creates a fork of the project on my account on Github (or equivalent)&lt;/li&gt;&lt;li&gt;It pulls, via Git (or equivalent), the very version of Program X that I am running currently. Now, this is important because I don't want to worry about different behavior in the program, I don't want to deal with a newer version of the program requiring different versions of libraries. I want the same thing I just ran, with the same bug, and I want the source code that generates it.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The build environment is all set up. I don't want to hunt for build dependencies, compiler options, etc. Enough said. "apt-get -b" Seems to do most of what I described thus far, minus the crutial Git part.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;I fix my problem. I make my changes, commit, and push. It shows up on upstream's Github fork queue (or equivalent). They decide whether to accept it.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Github has already done a great part of this, compared to a few years ago, by lowering the barrier to entry with the fork queue. Install via source already exists in apt. Would it be a huge task to coordinate the two?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think that I would probably have scratched a few itches by now if it were this straightforward. Instead, I have to look up the specific build setup for the project (on the project's site, not Ubuntu's site), figure out build dependencies, etc. Or, I can do apt-get -b, but then it's not ready to commit my changes back (afaik).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The limit of my patience, and free time, is reached much earlier in the process as things currently stand. Remember, this is for people who are perhaps a few levels less involved than the sort of user who would run the bleeding edge Ubuntu Beta. This is a regular user with some coding skills, who might be able to fix a problem or two if the setup were handed to them. They have a different mentality. This is about getting a new class of developers involved.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Again, I'm ignorant about the details of package management and open source project management, so I'm probably leaving holes in this idea that I don't know about. I'm just a developer with an idea. The question is, can these holes be ironed out, or does this have a fundamental problem because of package management, as it stands today?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Or does this already exist and I just never heard of it? (in which case, it should just be promoted more!)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-1669457924176050154?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/1669457924176050154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=1669457924176050154' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1669457924176050154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1669457924176050154'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2011/04/lower-barrier-for-scratching-open.html' title='Lower the Barrier for Scratching Open Source Itches!'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-1349234404922009183</id><published>2011-01-29T23:16:00.003-06:00</published><updated>2011-01-30T00:00:44.335-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell_synth'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><title type='text'>I found the perfect project to dive into Haskell</title><content type='html'>I've had a recurring project in my life, a modular software synth. &lt;a href="http://en.wikipedia.org/wiki/Synthesizer#Components"&gt;See here&lt;/a&gt; to get an idea of what I'm doing. The difference being that with software synths, you're not limited to how many components you have and how they're configured. I somehow thought I came to this revelation on my own years ago, but there's plenty of this sort of thing out there, such as &lt;a href="http://www.audiosynth.com/"&gt;SuperCollider&lt;/a&gt;, which sounds like it's fairly popular.&lt;br /&gt;&lt;br /&gt;I've been trying to get into Haskell, but have been struggling to get myself out of my Python comfort zone. A friend of mine actually told me about SuperCollider recently, and I realized that my own synth would be the perfect project to get me started on Haskell, and one day last week I got inspired to get started. I found a simple example to start with of a sine wave being played through Pulse Audio and I went from there. &lt;a href="https://github.com/orblivion/Haskell-Synth"&gt;Here's my repo&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately, you need PulseAudio to run this. I'm working on either getting Alsa output or file generation working soon.&lt;br /&gt;&lt;br /&gt;When I was making this a few times before, I made it in C++, the latest instance being several years ago. Amazingly enough, despite still being a novice in the language, I found that doing this in Haskell is easier. The infinite lazy lists work perfectly as signals. Before I considered each component to be an object that had a value, and input signals. And I had to have a global "tick" that conveyed info between items. (And I thought that was really neat at the time.) Now I just have components be functions that "output" (return) infinite lists, and take infinite lists as inputs. It all sortof just sorts itself out.&lt;br /&gt;&lt;br /&gt;Speed is sacrificed to be sure, at least so far, but real-time synths have been made for Haskell, so I bet I can profile it and optimize it significantly.&lt;br /&gt;&lt;br /&gt;Also you will notice that everything is hard coded! I sortof like it that way, it's amusing, particularly when it starts making beat sequences (which is a point I got to in my old version), but I'll probably make an interface at some point. Or maybe not, Haskell is a nice interface.&lt;br /&gt;&lt;br /&gt;Here's why I'm writing now of all times though. On top of being functional with the lazy infinite lists and such, Haskell also has a type system from Nazi Germany. This is actually an advantage, though. I have some trouble remembering all the unit conversions involved in the oscillators, when I'm dealing with cycles, seconds, and samples. So today, I made a type framework that provided functions that did the conversions properly. When I was writing out an improved version of my oscillator function, I used these types.&lt;br /&gt;&lt;br /&gt;It took me a long time to figure out exactly how I wanted it all to work, and how to make it work. I would start on an expression, and then realize that I was adding different units, and Haskell wouldn't let me do it. Or sometimes the compiler told me so. But eventually I got through it. &lt;a href="http://pastebin.com/KmPn8uJj"&gt;This is the monstrosity that resulted.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And the kicker: I used this to make a new version of the square wave oscillator, and it sounded exactly the same as the old one, &lt;i&gt;the first time I ran it.&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-1349234404922009183?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/1349234404922009183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=1349234404922009183' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1349234404922009183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1349234404922009183'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2011/01/i-found-perfect-project-to-dive-into.html' title='I found the perfect project to dive into Haskell'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-3365435037514887745</id><published>2011-01-02T17:45:00.006-06:00</published><updated>2011-01-02T18:04:36.973-06:00</updated><title type='text'>Testing Multiple Login Sessions Simultaneously</title><content type='html'>&lt;div&gt;One annoyance in developing websites is that you sometimes have to log in and out all the time to test interaction between multiple users.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Have you ever visited or administered a website (say, www.example.com) which lets you visit "www.example.com" or "www2.example.com", etc, and doesn't forward to "example.com"? Did you ever try logging in at one subdomain, and then switch to another? You'll be logged out, it's a different login session. If you needed to test something remotely with multiple users logging in at once, that's a nice trick to use.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now let's do the same thing locally (*nix systems only afaik, sorry):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;In /etc/hosts you should see:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="white-space: pre;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre&gt;127.0.0.1 localhost&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Add the following:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;127.0.0.1 localhost2&lt;br /&gt;127.0.0.1 localhost3&lt;br /&gt;127.0.0.1 localhost4&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And so on for however many you need. Now each one will access your site with a different session, so you can log in as a different user for each.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-3365435037514887745?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/3365435037514887745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=3365435037514887745' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/3365435037514887745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/3365435037514887745'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2011/01/testing-multiple-login-sessions.html' title='Testing Multiple Login Sessions Simultaneously'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-3634689946251510003</id><published>2010-12-18T23:15:00.028-06:00</published><updated>2010-12-19T11:04:55.440-06:00</updated><title type='text'>Cryptonomicon: A Lesson for my Hyper-Logical Friends</title><content type='html'>&lt;div&gt;I'm currently reading Cryptonomicon by Neil Stephenson. I'm not very acquainted with literature at large, so forgive me if I'm being ignorant here, but it seems that this book is unique or among very few that are in wide release and yet somewhat esoteric. That is to say, anybody can appreciate it, but I think it speaks specifically to computer programmers and mathematicians, and may not be 100% understood by those who are unfamiliar with certain mathematical and engineering concepts, and who don't share that mentality. Then again, the purpose could be to provide some insight to outsiders who may want to understand the hyper-logical nerd mentality. Tom Wolfe seems to do a similar thing, for instance, with the investment bankers in Bonfire of the Vanities.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Though I think Neil Stephenson must have a closer personal connection with this mentality. It's a great book for a nerd because it's literature we can really relate to. It's told from the perspective of those of us who try to make logical sense of everything, see patterns all around us, and are confused by strange things like social niceties.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All in all I think it teaches an important lesson to nerds and non-nerds alike. I only just now crossed the 1/3 way mark (it's like 1100 pages), but I just came across some particular dialog which I think is particularly insightful. In this scene, Randy Waterhouse pulls Eberhard Föhr aside during a business meeting, and explains to him why, for their own legal protection, information has been withheld from them by one of their business partners, Avi. Ebehard, being of this nerd mindset, is frustrated that his business partners are not behaving logically. Randy, being of the same mindset but somewhat more enlightened, explains to Ebehard the realities of dealing with illogical people, but he does so in logical terms that Ebehard can relate to. This conversation is amusing like a lot of things in this book, because it demonstrates how us analytical types like to deconstruct everything.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Rather than risk inviting Neil Stephenson's lawyers (I have no idea how likely a scenario this is be but I don't care to do the research right now) I'll just invite you to &lt;a href="http://books.google.com/books?id=FUha9wJrSXMC&amp;amp;lpg=PP1&amp;amp;dq=cryptonomicon&amp;amp;pg=PA282#v=onepage&amp;amp;q&amp;amp;f=false"&gt;read this page via Google Books.&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I appreciate a couple things about this passage. Firstly, I appreciate that Randy's character is sort of an enlightened techie, who we should aspire to, who respects the qualities of other sorts of people, even if he doesn't understand their mentality. Business people clueless about technology, idealistic designers with a vision, techies who can't design a usable interface to save their life, we should all accept our own limitations of understanding, respect the others, and occasionally yield our own ideals for the sake of other ones. (ex: if "doing it right" means taking twice as long, and failing in the market, what use is your ideally laid out code if nobody's going to use it?)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The other thing I like about this passage is, as I mentioned above, the logical way that it approaches illogical people. Some nerds have a tendency to refuse to approach the world in anything other than a logical manner. Normal People may try to explain to them that the world, particularly other individuals, aren't rational at all, and we should stop seeing things so logically. I include myself in this group of nerds, so honestly, this line of argument is ridiculous to me. The universe is logical. But, I think that sometimes we as nerds are just Doing It Wrong, and we can take a cue from Randy here.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What we need to do is to appreciate that the fact that people act irrationally, out of emotion, is just a condition of the world. Just as we accept that animals are irrational, or that the sun is hot. It's a datum. Further, accept that you yourself, the nerd, are also emotional, particularly when people don't act logically. This frustration with others' illogical behavior is based on an expectation for people to act contrary to their nature. You're ignoring a data point. You're mad at the sun for being hot. You're a non-techie who's mad at your computer for doing something other than exactly what you told it to. Now look who is being irrational? I'm going to agitate a little and propose that we are in fact being hypocritical here.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The main problem I think we sometimes have is the distinction between Logic and Logical Faculties. The expectation of perfection in Logic is not the same as expecting a human to have perfect Logical Faculties. The universe works by rational laws. People are part of the universe, so their workings are rationally explainable. But this is entirely distinct from their Logical Faculties being able to perfectly model the world around them. Furthermore, people's Logical Faculties being able to model the world around them is distinct from their ability to defend it from any of their Emotional Faculties getting in the way. We humans are but animals who happen to possess a limited amount of logical faculties.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Expecting people to act in a rational straightforward manner is like expecting a computer to compute beyond its capacity. A problem may be Logically solvable. There is a perfect Logical progression toward the answer. If we treated computers the same way we sometimes treat other humans, we would demand that we should be able to stick the problem into a computer and get an instant output. But again, Logical Faculties are in limited supply. Somehow we don't seem to have a problem accepting this in computers. In fact, we have entire sub-fields of computer science, taking RAM, HD, and time limitations as data, and creating a whole new set of Logical problems. Why not accept the same limitations and challenges in humans?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Perhaps it's that there is one fundamental difference between computers and humans, which is that our departure from being perfect logic solvers is not just in our processing capabilities, but also, as Randy pointed out in the passage linked above, in our interfaces. Human interfaces are more like neural networks than serial connections. To gain access to the Logical Faculties, one must enter a pattern that is accepted by the neural network. The patterns include such things as social niceties and innuendo. Some of us have simpler interfaces than others. (And as Randy described, some may even require other humans to act as intermediate interfaces. When I worked at Oracle, there was a guy who was fluent in both Engineer and Customer, and intermediated all conversation. I understand this is a common thing to have in a company.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And you, the nerd, are a neural network, at your core, not a Turing machine. You operate in that domain. That means you have the natural ability, however impaired by years sitting in front of the computer, to interface with other neural networks, if you would just accept your nature. This is in fact the only way you can communicate with other humans, so you might as well accept it for what it is. You may try to approximate a Turing machine, but your neural network nature will still show on occasion. For instance, as I pointed out above, when you are frustrated about others not behaving like Turing machines.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-3634689946251510003?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/3634689946251510003/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=3634689946251510003' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/3634689946251510003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/3634689946251510003'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2010/12/cryptonomicon-lesson-for-my-hyper.html' title='Cryptonomicon: A Lesson for my Hyper-Logical Friends'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-1410413499752719095</id><published>2010-11-15T00:48:00.004-06:00</published><updated>2010-11-15T01:43:00.713-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='allcombinations'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>allCombinations: leaveOut</title><content type='html'>&lt;b&gt;leaveOut&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Ok, on my previous post I brought up a small Python module I was inspired to throw together while writing tests. It's still sitting in a gist, though I'll probably move it to a real repo before too long:&lt;br /&gt;&lt;br /&gt;&lt;a href="https://gist.github.com/674715"&gt;https://gist.github.com/674715&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So I admit, as I was posting it, it occurred to me that to a large extent this stuff could be replaced with a nested for loop. For instance, this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;for lst in allCombinations([1, 2, oneOf(3,4), oneOf(5,6)]):&lt;/pre&gt;&lt;br /&gt;can be pulled off with:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;for x in (3, 4):&lt;br /&gt;for y in (5, 6):&lt;br /&gt;   lst = [1, 2, x, y]&lt;/pre&gt;&lt;br /&gt;Not a huge gain necessarily on my part. So as I was using it in my testing I realized I once again had engineered something for a tiny use that, neat as it is, could have been done much faster by brute force. But then, I realized another thing I could add that would make my code much more concise. I've added another keyword called "leaveOut". It lets you opt to not have the element show up at all. Here's an example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;allCombinations([1,2, oneOf(3, leaveOut), oneOf(4, leaveOut)])&lt;/pre&gt;&lt;br /&gt;This will return:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;[ [1, 2, 3, 4], [1, 2, 3], [1, 2, 4], [1, 2] ]&lt;/pre&gt;And of course, the "leaveOut" case will omit dictionary entries and object data members as well.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;BTW&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I should also mention another use case I thought of, "leaveOut" aside, that might be a real pain to do without an aide such as allCombinations, which is dynamically created structures, with an arbitrary amount of variables:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;allCombinations( [ oneOf(1, 2) ] * x )&lt;/pre&gt;&lt;br /&gt;I've just generated all possible lists of either 1 or 2, of an arbitrary length, which can be set at runtime. Or how about something a bit more fun:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;allCombinations( [ oneOf( *range(y) + [leaveOut] ) for y in range(x) ] )&lt;br /&gt;&lt;/pre&gt;Taking all combinations of lists of length x, where each element can equal any integer from zero to its index, and then adding combinations where items are omitted. Not horribly useful, but complicated.&lt;br /&gt;&lt;br /&gt;To do these in a standard way you'd need x for loops, which you can't do directly. (I bet you could do it with recursion).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Fixes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'll also mentione that I fixed a couple general errors. oneOf on Data members had a big bug. And now if you don't have oneOf in your structure, allCombinations just returns a list containing only the original structure, instead of looping to death.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-1410413499752719095?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/1410413499752719095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=1410413499752719095' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1410413499752719095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1410413499752719095'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2010/11/allcombinations-leaveout.html' title='allCombinations: leaveOut'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-6526394923062999111</id><published>2010-11-12T15:34:00.005-06:00</published><updated>2010-11-12T15:53:52.639-06:00</updated><title type='text'>allcombinations - generating combinations of python structures</title><content type='html'>Alright, on a whim I decided to make another tricky thing in Python. This one is less of a hack, and is more likely to be useful.&lt;br /&gt;&lt;br /&gt;So let's say you want to do something with all combinations of... something.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;[5, 6, oneOf(7,8,9), oneOf(10, 11, "shazaam")]&lt;/pre&gt;&lt;br /&gt;So you want to turn this structure into all the possibilities represented within:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;[&lt;br /&gt;[5, 6, 7, 10],&lt;br /&gt;[5, 6, 7, 11],&lt;br /&gt;[5, 6, 7, "shazaam"],&lt;br /&gt;[5, 6, 8, 10],&lt;br /&gt;[5, 6, 8, 11],&lt;br /&gt;[5, 6, 8, "shazaam"],&lt;br /&gt;[5, 6, 9, 10],&lt;br /&gt;[5, 6, 9, 11],&lt;br /&gt;[5, 6, 9, "shazaam"],&lt;br /&gt;]&lt;/pre&gt;&lt;br /&gt;Well with allcombinations, you can do just that:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;from allcombinations import allCombinations&lt;br /&gt;&lt;br /&gt;allCombinations( [5, 6, oneOf(7,8,9), oneOf(10, 11, 12)] )&lt;/pre&gt;&lt;br /&gt;&lt;a style="font-weight: bold;" href="http://gist.github.com/674715"&gt;Here it is.&lt;/a&gt; The gist includes more complicated example.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Features&lt;/span&gt;&lt;br /&gt;The oneOf should be able to reside almost anywhere in your expression. It can be in a list (as seen here), in a dict, or even in the attribute of an object. It can also reside in a list within a dict within an object's attribute, etc, as long as it's nowhere within an unsupported container type.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Limitations:&lt;/span&gt;&lt;br /&gt;This will only work if oneOf resides in a list, dict, or an object's attributes. It shouldn't work anywhere within a set, or any other structure I can't think of. If you try it in something unsupported, the oneOf object should just stick around in all your combinations.&lt;br /&gt;&lt;br /&gt;I'm probably actually going to use this, particularly (again) for testing. Anyone else think they'd find it useful? Should I package it?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-6526394923062999111?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/6526394923062999111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=6526394923062999111' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/6526394923062999111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/6526394923062999111'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2010/11/allcombinations-generating-combinations.html' title='allcombinations - generating combinations of python structures'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-2090118035059062933</id><published>2010-11-12T09:39:00.008-06:00</published><updated>2010-11-12T10:39:11.943-06:00</updated><title type='text'>Testing (Django) views with pyquery</title><content type='html'>&lt;a href="http://pypi.python.org/pypi/pyquery"&gt;PyQuery&lt;/a&gt; is basically what it sounds like. Using &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; syntax, you can query and even manipulate XML files. Obviously we don't (yet!) have Python in the browser, so it's not useful in the same domain, but it can help out in dealing with XML in general, in the same way as, say, lxml, but without having to learn about things like ElementTree for simple cases. It's particularly good for XHTML because jQuery (and thus PyQuery) uses CSS syntax for class= and id=. Which brings me to how I'm using it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;from django.test.client import Client&lt;br /&gt;from pyquery import PyQuery&lt;br /&gt;from django.test.testcases import TestCase&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;class TestSomeViews(TestCase):&lt;br /&gt;&lt;br /&gt;   def testAView(self):&lt;br /&gt;&lt;br /&gt;       client = Client()&lt;br /&gt;&lt;br /&gt;       ...&lt;br /&gt;&lt;br /&gt;       response = client.get("/someurl/")&lt;br /&gt;&lt;br /&gt;       self.assertTrue("expected text" in PyQuery(response.content)("#someid").html() )&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;(If you're unfamiliar with testing Django views, &lt;a href="http://docs.djangoproject.com/en/dev/topics/testing/#module-django.test.client"&gt;see this&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;For some basic tests, you can just search the entire response html, and  not have to worry about where it shows up. But suppose you're searching  for a username in a particular part of your response. You're pretty  likely to find that username elsewhere on the page, so you have to  select out the part of the file you expect it. I think this is much  easier than using a regex.&lt;br /&gt;&lt;br /&gt;So what this bit of PyQuery does is find the tag with the id of "someid" (presumably there's only only one, being an id), and returns the html within that tag. (If you search for a class that returns multiple tags, it seems that a simple call to .html() will only return the contents of the first one. This very well may match jQuery's behavior, I'm admittedly not that familiar, but just a head's up.)  For more details look at the &lt;a href="http://packages.python.org/pyquery/api.html"&gt;PyQuery API&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-2090118035059062933?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/2090118035059062933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=2090118035059062933' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/2090118035059062933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/2090118035059062933'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2010/11/testing-django-views-with-pyquery.html' title='Testing (Django) views with pyquery'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-1235413319916005675</id><published>2010-10-27T00:52:00.004-05:00</published><updated>2010-10-27T01:15:04.515-05:00</updated><title type='text'>Django Model Validation</title><content type='html'>I'm really excited about model validation, in Django circa 1.2. It's going to save me from the disastrous hack of ModelForms I've used so far. One wants something to validate data before saving it, since validating it &lt;span style="font-style: italic;"&gt;by&lt;/span&gt; saving it is apparently a Bad Idea, since you may have already made changes to the database by the time the error is thrown.&lt;br /&gt;&lt;br /&gt;I wanted this done automatically, and Django only had form validation until 1.2, so I hacked forms into some sort of all-purpose wrapper for models. I've since learned to program Django like an adult, and model validation came around just in time anyway. But there's a problem I have with it.&lt;br /&gt;&lt;br /&gt;First I should point out that there's a few different things that get validated, but the two I'll point out are A) checking that required fields are set and B) whatever I put into the clean() function. Judging by some errors I've gotten while debugging/testing, Django seems to be checking B before A.&lt;br /&gt;&lt;br /&gt;Now, when I use a ModelForm, sometimes I want to use the commit=False option when I save. This returns a model that hasn't been committed to the database. Sometimes there's extra data I want to add to the model that the form didn't supply. Sometimes that data is in fact necessary for the model to be valid. So clearly Django shouldn't check A, and it doesn't. Here's the funny thing though: it does check B. Why would it do that? I can understand checking when I call is_valid(), I can control when that's called, making sure I added everything first.&lt;br /&gt;&lt;br /&gt;So far the consequences of checking B early have been trying to access members that haven't yet been set, in my clean() function. So in clean() I just check for those items, and just let it pass if they don't exist. I figure, yeah, it'll pass certain tests when it shouldn't. But if it's really running through validation (not just B as in the save (commit=False) case) that means it'll catch the missing members on the A pass anyway.&lt;br /&gt;&lt;br /&gt;Maybe I got something wrong, but I thought it was a weird design decision.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-1235413319916005675?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/1235413319916005675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=1235413319916005675' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1235413319916005675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1235413319916005675'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2010/10/django-model-validation.html' title='Django Model Validation'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-5861468665941316699</id><published>2010-10-05T10:08:00.006-05:00</published><updated>2010-10-05T10:49:12.622-05:00</updated><title type='text'>Significant Whitespace in Python Data Structures</title><content type='html'>I recently wrote a program in Python for parsing files. I'm pretty naive still when it comes to functional programming, but I'm  still excited about it, so I wanted it to be more functional in style. It had a complicated data structure representing the file structure, instead of a loop with bunch of if-thens. By Python standards I may have gone a bit overboard. Guido probably would not have approved of my code (not to mention what follows in this blog post).&lt;br /&gt;&lt;br /&gt;So as a result, most of the program became whitespace irrelevant. Huge dicts of lists of tuples, etc. It made me think that relevant whitespace might become handy for data too. And while talking on IRC about it this morning I realized I could sortof hack it using decorators and generators. So here's what it looks like:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://gist.github.com/611646" target="_blank"&gt;http://gist.github.com/611646&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So I have two examples:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;example.py&lt;/span&gt; - This shows how you can define a more complicated structure with whitespace instead of a bunch of ){(}[].&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;inlinefunc.py&lt;/span&gt; - This demonstrates a sort of side-effect benefit. You can have multi-line functions inline in a list (or tuple or dict). Usually you're stuck with lambdas, and of course that starts to look confusing too.&lt;/li&gt;&lt;/ul&gt;I'd like to clean up the syntax. Obviously having to have a decorator before and a yield after isn't great. I'll have to think about how I could do that. Maybe make an even dirtier hack by doing introspection.&lt;br /&gt;&lt;br /&gt;Any thoughts?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-5861468665941316699?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/5861468665941316699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=5861468665941316699' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/5861468665941316699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/5861468665941316699'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2010/10/significant-whitespace-in-python-data.html' title='Significant Whitespace in Python Data Structures'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-5537764820030591756</id><published>2010-03-13T17:30:00.005-06:00</published><updated>2010-03-13T17:51:15.949-06:00</updated><title type='text'>A useful script: copytoclipboard</title><content type='html'>Another quick tool I figure I'd share. Made this one a while ago. When you're doing stuff on the command line and you need to copy something for a desktop app, you end up having to select text on your terminal screen. Well if it's a big text file, you have to copy, paste, scroll to the next part, copy (make sure you didn't copy any part twice), paste, etc.&lt;br /&gt;&lt;br /&gt;Well, copytoclipboard takes standard input and puts it into the gtk clipboard (haven't tried this on KDE).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 255, 51);"&gt;#!/usr/bin/env python&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 255, 51);"&gt;import sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 255, 51);"&gt;import pygtk&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 255, 51);"&gt;pygtk.require('2.0')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 255, 51);"&gt;import gtk&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 255, 51);"&gt;c = gtk.Clipboard()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 255, 51);"&gt;c.set_text(''.join(sys.stdin.read()))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 255, 51);"&gt;c.store()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;For instance, to paste this code, I went into my terminal and typed:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 255, 51);font-family:courier new;" &gt;cat copytoclipboard | copytoclipboard&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;and pasted the results here. For a less confusing example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 255, 51);font-family:courier new;" &gt;uptime | copytoclipboard&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;lets me paste this:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 255, 51);font-family:courier new;font-size:85%;"  &gt;17:42:14 up  3:23,  2 users,  load average: 0.35, 0.39, 0.41&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;EDIT&lt;/span&gt;: Or I could just do a google search and find that &lt;a href="http://linuxtidbits.wordpress.com/2008/02/22/command-line-to-clipboard/"&gt;xclip already exists&lt;/a&gt;. Oh well.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;EDIT2&lt;/span&gt;: No, xclip seems to be its own thing. I just tried it, doesn't seem to work with gtk. I guess I still win!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-5537764820030591756?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/5537764820030591756/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=5537764820030591756' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/5537764820030591756'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/5537764820030591756'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2010/03/useful-script-copytoclipboard.html' title='A useful script: copytoclipboard'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-5531796306490216270</id><published>2010-02-25T10:03:00.002-06:00</published><updated>2010-02-25T10:12:56.917-06:00</updated><title type='text'>"New Music" script</title><content type='html'>I just thought of a script (can't test it at work so I'll actually write it later, but it'd be only a few lines long). Would work thusly:&lt;pre&gt;Desktop&gt;newmusic britney_spears_leak_trance_remix.ogg ~/music/various/&lt;/pre&gt;It would act like mv, just move the song over to the "various" directory, but it would also add a symlink to&lt;br /&gt;&lt;pre&gt;~/music/new/&lt;/pre&gt;That way, I'll remember to give it a listen. And when it's no longer novel I can just delete the symlink. Otherwise this crap gets accumulated on my Desktop. Maybe happens to you too.&lt;br /&gt;&lt;br /&gt;Maybe it could be made into a Nautilus script or something, but that seems a bit more tricky if you're dealing with drag n drops.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-5531796306490216270?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/5531796306490216270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=5531796306490216270' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/5531796306490216270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/5531796306490216270'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2010/02/new-music-script.html' title='&quot;New Music&quot; script'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3916802132854520262.post-7745475658269682151</id><published>2010-02-14T17:06:00.003-06:00</published><updated>2010-02-14T17:39:21.641-06:00</updated><title type='text'>Making new twitter followers marginally more convenient</title><content type='html'>Well, one tiny annoyance that I just randomly decided I felt like itching - I get a handful of emails from twitter saying so-and-so is following me. Usually it's somebody I'm not interested in, but on occasion it's a friend. What annoys me is that I have to open their profile to see. I'd prefer to see the bio and their last few tweets in the email itself. Would help me decide much faster. Well, I've started on a real hack of a solution. It should make it a little less annoying:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://gist.github.com/304335"&gt;http://gist.github.com/304335&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Look it over. If you trust it, run it on a command prompt (works on Linux, all I can say). It asks for your gmail password. It opens browser tabs for all the twitter accounts that have followed you that are still in your gmail inbox.&lt;br /&gt;&lt;br /&gt;Now, I'm making some wild assumptions about the emails that Twitter is sending us (namely that the first Twitter url is the profile in question), so this may not open up everything correctly. Especially if Twitter changes the email. So, I also open up a tab with a gmail search for all those emails. You can look it over and confirm that it opened up the right tabs, plus this helps you archive them right away.&lt;br /&gt;&lt;br /&gt;If it doesn't work, do this first:&lt;br /&gt;&lt;br /&gt;&lt;a href="https://www.google.com/accounts/DisplayUnlockCaptcha"&gt;https://www.google.com/accounts/DisplayUnlockCaptcha&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I guess it tells Google that your computer isn't engaging in any anti-human activities. I had to do it.&lt;br /&gt;&lt;br /&gt;I may eventually have it generate an html page with all the useful info right there, so you can look it over quicker. I'll also look for a way to have a GUI password entry thing, so you won't need a cmd prompt. Or, you know, if any of you Open Sourcerers want to do it yourself and send back the update, that would be great too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-7745475658269682151?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/7745475658269682151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=7745475658269682151' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/7745475658269682151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/7745475658269682151'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2010/02/making-new-twitter-followers-marginally.html' title='Making new twitter followers marginally more convenient'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3916802132854520262.post-4879817173934159280</id><published>2009-10-28T22:41:00.004-05:00</published><updated>2009-10-29T01:02:14.418-05:00</updated><title type='text'>Ping!</title><content type='html'>Pinging is the act of sending ICMP packets to another device, and waiting for a response. It's a good way of seeing if we're online, or if the hopeful recipient is online. It is prevalent enough that it's become slang for contacting someone, to see if they're around and listening. And it's gone beyond that; I just realized that Google Wave's use of "Pinging" someone makes it official in a way.&lt;br /&gt;&lt;br /&gt;But even in the ICMP packet sense, it was in a sense a slang usage. From &lt;a href="http://en.wikipedia.org/wiki/Ping"&gt;Wikipedia&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;"Mike Muuss wrote the program in December, 1983, as a tool to troubleshoot odd behavior on an IP network. He named it after the pulses of sound made by a sonar, since its operation is analogous to active sonar in submarines, in which an operator issues a pulse of sound at the target, which then bounces from the target and is received by the operator. (The pulse of sound in sonar is analogous to a network packet in ping)."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Here's the other half of the story. I always feel inclined to theme my computer. Really put some life into it. I thought of a really silly idea, and a great way how to do this today while sitting at the Skylark.&lt;br /&gt;&lt;br /&gt;So here's where it all comes together: &lt;a href="http://static.danielkrol.com/assorted/noisyping.tar.gz"&gt;Noisy Ping&lt;/a&gt; (for lack of better name)&lt;br /&gt;&lt;br /&gt;When you set this up, ping will emit a sonar sound. And if you get a response, you will hear a subdued version of the same sound.&lt;br /&gt;&lt;br /&gt;Code licensed under WTFPL, sound was from a creative commons site, so it's under Sampling Plus 1.0. Don't sue me if a whale tries to mate with your computer. Or if my program does something bad (though I promise I didn't mean to do anything bad, and that I'm running this on my own computer).&lt;br /&gt;&lt;br /&gt;This was sortof hacked together, because frankly I have better things to do than to do this "properly", but I did my best to make sure that the python script relayed ping's inputs and outputs and kill signals faithfully (though I have a failsafe SIGTERM, followed by SIGKILL, at the end). if you have any suggestions on how to make this more safe, less crash prone, more portable, etc, please feel free to send me a better version.&lt;br /&gt;&lt;br /&gt;And hell, it's &lt;i&gt;sortof&lt;/i&gt; useful too. If you're pinging something and you don't want to watch the terminal to see if you get anything back.&lt;br /&gt;&lt;br /&gt;So there you go.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-4879817173934159280?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/4879817173934159280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=4879817173934159280' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/4879817173934159280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/4879817173934159280'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2009/10/ping.html' title='Ping!'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-602781775653366872</id><published>2009-03-07T15:32:00.005-06:00</published><updated>2009-03-07T15:56:55.730-06:00</updated><title type='text'>What about a "rabbithole" paradigm for all GUIs?</title><content type='html'>I'm watching a presentation on Zimbra, and I'm noticing that the interface is really busy. I can begin to see why it must be a pain in the ass to set up and maintain (as I've heard). I know I'd hate to have to use it. Where I currently work, as I would imagine is the case at most large businesses, you have a million different services that you &lt;i&gt;can&lt;/i&gt; use, a couple of which you &lt;i&gt;have to&lt;/i&gt; use, and a couple which you &lt;i&gt;may&lt;/i&gt; want to use (the latter group will vary by person or group). A whole lot of things just don't get used by your group, but you keep hearing about it from the company above, it keeps showing up in your web interfaces, and it's just annoying.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ill-logic-tech.blogspot.com/2009/02/what-about-rabbithole-paradigm-for.html"&gt;A couple posts ago&lt;/a&gt; I mentioned an idea of a "rabbithole paradigm" for configurations. What if you did the same thing for your whole GUI?&lt;br /&gt;&lt;br /&gt;You start with a big button that says Zimbra. You click on it and get three buttons called Communication, Collaboration, and Settings. You click Communication and you get your email, chat. Click Collaboration you get file sharing, Wiki, etc. Settings gives you GUI settings and Account Settings, each of which gives you more things. Everything is completely straightforward, if cumbersome, as to where you should find them. Certainly no settings or shortcuts that you don't need are in your main interface.&lt;br /&gt;&lt;br /&gt;Well, that would make things a lot less confusing, and a pain to get to the services you need, because you have to go all the way down the rabbit hole to get to them. But, as you decide to use them, they would get added to your front page. This includes configuration too, I suppose, as I mentioned in my other post. That way, you always have exactly the services and settings you need and know how to use on your front page and in your menus.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-602781775653366872?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/602781775653366872/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=602781775653366872' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/602781775653366872'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/602781775653366872'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2009/03/what-about-rabbithole-paradigm-for-all.html' title='What about a &quot;rabbithole&quot; paradigm for all GUIs?'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-2533365527682100626</id><published>2009-02-20T16:04:00.002-06:00</published><updated>2009-02-20T16:07:10.631-06:00</updated><title type='text'>Backing up stuff from websites.</title><content type='html'>Ok so if I'm going to give in and start being a social media whore, can I at least back up my info? I know my friend Kevin was telling me that "open websites" let you can grab all your info from their DB. I wonder how possible that is for other sites. Could I, say, back up my Twitter contacts? My google reader feeds? My delicious links? (yet to join the latter two). I can concede that these outside sources know what I'm doing and what I'm interested in and who my friends are and where I live, but I don't like depending on them to keep my data.&lt;br /&gt;&lt;br /&gt;I should start by setting up IMAP for my Gmail account, sheesh...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-2533365527682100626?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/2533365527682100626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=2533365527682100626' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/2533365527682100626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/2533365527682100626'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2009/02/backing-up-stuff-from-websites.html' title='Backing up stuff from websites.'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-1365628204622387637</id><published>2009-02-20T15:55:00.004-06:00</published><updated>2009-02-20T16:00:37.036-06:00</updated><title type='text'>What about a "rabbithole" paradigm for configuration GUIs?</title><content type='html'>You get very basic settings on the main screen, but there's a button for things a bit more advanced. The screen that follows that button has categories, and each category again has buttons for things slightly more advanced. You go as far down the rabbithole as you feel comfortable. You could have everything be configurable, but it's not a choice between a Fischer Price toy and an Airplane Cockpit.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;And&lt;/i&gt;, and I think this is a kicker here, you &lt;i&gt;save&lt;/i&gt; which buttons you clicked, which screens you edited. So you sortof have your own customized config GUI. It's tailored to each user for whatever they feel comfortable with.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-1365628204622387637?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/1365628204622387637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=1365628204622387637' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1365628204622387637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1365628204622387637'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2009/02/what-about-rabbithole-paradigm-for.html' title='What about a &quot;rabbithole&quot; paradigm for configuration GUIs?'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-6022036917157567725</id><published>2009-02-14T19:51:00.002-06:00</published><updated>2009-02-14T20:03:24.922-06:00</updated><title type='text'>xmsg</title><content type='html'>Made a handy little script I wanted to share.&lt;br /&gt;&lt;br /&gt;I call it xmsg:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;"$@" | xmessage -file -&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, you can put xmsg before any program whose console output you want, and it'll show up in a (albeit archaic looking) dialog box. This is useful when you want to know the console output of something just with the Alt-F2 run dialog, and you don't want to bother opening an actual console.&lt;br /&gt;&lt;br /&gt;Put it on the PATH so you don't have to put the whole path to the script, you can just type "xmsg" followed by your command into the Alt-F2 menu (or a console if you want). Quick example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;xmsg df -h&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Will give you a nice popup telling you how much space you have on each mount. Now wasn't that more convenient than having to open a console?&lt;br /&gt;&lt;br /&gt;How it works (in case a little education can come of this).&lt;br /&gt;&lt;br /&gt;"$@" represents all arguments to the script after the name of the script itself. So, this just runs the command you put after xmsg. This pipes to xmessage. xmessage generally makes a dialog with whatever you give it as an argument, but if you say "-file" it will read from a file. If you give "-" as the file, it will read from standard in, which in this case is the output of "$@".&lt;br /&gt;&lt;br /&gt;The quotes, btw, on "$@", are because of Bash's annoying quoting rules. Not using them will, I am told, cause arguments with spaces to retokenize.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-6022036917157567725?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/6022036917157567725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=6022036917157567725' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/6022036917157567725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/6022036917157567725'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2009/02/xmsg.html' title='xmsg'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3916802132854520262.post-5063019191823537658</id><published>2009-02-10T10:21:00.002-06:00</published><updated>2009-02-10T10:28:57.342-06:00</updated><title type='text'>Twitter</title><content type='html'>I'm only announcing my Twitter usage here for now because I got a great quote from my friend Tim, and it won't fit in Twitter's max characters:&lt;br /&gt;&lt;br /&gt;"dude, twitter is perfect for you. you send out a message to no one in particular.  If anyone wants to listen, then you're talking to them.  You do that without the internet."&lt;br /&gt;&lt;br /&gt;I guess if you want to follow me:&lt;br /&gt;http://twitter.com/orblivion&lt;br /&gt;&lt;br /&gt;I suppose I'll be extra cool and get identi.ca soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-5063019191823537658?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/5063019191823537658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=5063019191823537658' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/5063019191823537658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/5063019191823537658'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2009/02/twitter.html' title='Twitter'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-4163279819787007826</id><published>2009-01-28T06:58:00.001-06:00</published><updated>2009-01-28T07:20:30.241-06:00</updated><title type='text'>Where is Google Apps free edition?</title><content type='html'>This answered my question:&lt;br /&gt;&lt;br /&gt;&lt;a href=http://googlesystem.blogspot.com/2008/11/free-google-apps-more-difficult-to-find.html&gt;http://googlesystem.blogspot.com/2008/11/free-google-apps-more-difficult-to-find.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This gave me the same feeling as discovering a secret area in a video game.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-4163279819787007826?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/4163279819787007826/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=4163279819787007826' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/4163279819787007826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/4163279819787007826'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2009/01/where-is-google-apps-free-edition.html' title='Where is Google Apps free edition?'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-7473639566993145296</id><published>2008-11-24T09:59:00.000-06:00</published><updated>2008-11-24T11:20:56.186-06:00</updated><title type='text'>Joe sent me</title><content type='html'>I moved into a new place recently. I need Internet access, and I wanted to avoid giving any more money to AT&amp;T, and I've heard that Comcast isn't much better. I looked into &lt;a href=http://www.copowi.com&gt;Copowi&lt;/a&gt; first. We couldn't get them to work at our last apartment (though it's at LEAST 50% AT&amp;T's fault, I'm sure more). I'd say they're not too bad, I had a support ticket and a support person that was willing to try different options to get my stuff to work. In the end, they refunded my money and even let me keep my modem. I was thinking it over again; do I want to deal with AT&amp;T for a phone line again, and then wait for Copowi, potentially dealing with the same fiasco? Well this made my decision very simple:&lt;br /&gt;&lt;br /&gt;&lt;a href=http://www.copowi.com/?q=surviving-the-depression&gt;Copowi: Preventing The Depression&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Thanks, but I'll get my information "they don't want you to know" from Alex Jones, and I'll get my Internet access from &lt;a href=http://www.speakeasy.net&gt;Speakeasy&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'd heard about Speakeasy from a couple people. They're a smaller ISP like Copowi. One person told me he used it and they had great service. Turns out, I can get the nets from them without even getting a phone line from AT&amp;T. (Copowi doesn't offer that in Chicago yet, though I think it does in other cities). Speakeasy is pretty expensive (I'm too embarrassed to give the actual amount), you can look up the rates yourself. But it's worth it to not have to give money to or otherwise deal with The New AT&amp;T (you can ask me about my experience with them if you'd like, I won't get into it here, this post is too long as it is). Plus, I'm paying for very impressive service, as you will soon see.&lt;br /&gt;&lt;br /&gt;The following might seem like trivial reasons to fawn over a company, but think of all the little annoyances that come up when you deal with companies. Particularly telecom. As usual, it's the small things that make a company great.&lt;br /&gt;&lt;br /&gt;I went to Speakeasy's site to see if they were available in my area. For some reason the form got confused about my zip code. There was another form below, however, to request someone to contact me to help. I chose email over phone (I'm an engineer, I don't like to talk to people). Plus email is much more out of the way.&lt;br /&gt;&lt;br /&gt;So I believe the next day I get an email from the guy. I asked him about my address, and he responded saying that I should be good, though I can't get more than 1.5 Mbps. I fire off a ton of questions at him all day, (it's a tough decision, a year contract, a high price). He responds to all my questions, probably within 15 minutes every time. I ask at one point if I can use a modem I had on hand (from copowi) instead of the modem that comes with the plan.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;"There is no real way to tell as it is all based on the chipset used to sync with the dslam at the central office.  I can definitely set up the order for you using your own modem, and if worse comes to worst and it doesn't work you can just get our Modem if you like."&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;See, that strikes me well, because he's a sales guy, but he uses terms like chipset. Good to know that the people selling me stuff know what they're talking about.&lt;br /&gt;&lt;br /&gt;Eventually I say that I'm interested. He sends me a form to fill out and fax (I preferred not to send my credit card number over email or cell phone, and I didn't feel like asking about GPG). Today I get my form email giving the details of the account. I was impressed by the fact that this form email said the following:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;"You have instructed your sales person to NOT order hardware for this installation. You have reported owning the following bridge/router:&lt;br /&gt;&lt;br /&gt;Broadxent 8012-V&lt;br /&gt;&lt;br /&gt;If an onsite technician attempts to deliver unordered hardware, simply inform them that you have your own, approved and supported CPE."&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;So they got my modem model wrong, but think about the fact that they had this option in a form email. I would have expected just a lack of charge for the modem, or they would charge me, but then the support guy would tell me "yeah, ignore that. I put in a note". I'm impressed that "customer has his own modem" is a standardized option for them.&lt;br /&gt;&lt;br /&gt;So I log into my account, and find that I can easily change my mailing and shipping address. The order info page has more technical and contact info (for the folks setting up my connection) than I know what to do with. It has a list of 8 "Stages" to getting a working connection (Order Received, Order Placed, Install Confirmation, IP Addresses &amp; Circuit Configured, etc). It shows details for each, including how long I should expect to wait, and of course which one I'm currently on. And, there's a dropdown box where I can choose how often I want email status updates (24, 48, 72, hours, or never) Underneath, there's some sort of "up to the minute report":&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;"The work log below represents the available documented efforts of Speakeasy and vendor (as indicated by their respective logos) to complete installation of your service.&lt;br /&gt;&lt;br /&gt;Speakeasy's service activation team proactively works to install your circuit at the highest level of priority. This real-time installation progress report provides the most current, complete and accurate update on your installation status...."&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Wow. Overkill, honestly. Though, if this were for a business I would probably appreciate this more.&lt;br /&gt;&lt;br /&gt;To top it all off, while I wait for my DSL connection, they offer a complimentary dialup connection that I can use right now. I don't have a phone line to use it on, but still, that's some really slick Business Fu if you ask me.&lt;br /&gt;&lt;br /&gt;One thing I don't really like is that the prices he gave me over email don't seem to be the same scheme that they have posted on their site. I may have just gotten confused on that though. And yes, for sending my credit card info, they should have had an encrypted web form for ordering service. Heck maybe they did, I didn't check, but I sortof wanted to go through this guy, since he was already helping me out and could sort out any issues I had, plus maybe he's getting commission. Finally, for some reason they didn't send my password or account number in my form email, but I emailed the support guy and got those right away.&lt;br /&gt;&lt;br /&gt;There's more to come with this, I'm sure. If it's anything spectacular I may post again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-7473639566993145296?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/7473639566993145296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=7473639566993145296' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/7473639566993145296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/7473639566993145296'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2008/11/joe-sent-me.html' title='Joe sent me'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-4952203639414010726</id><published>2008-11-16T10:00:00.000-06:00</published><updated>2008-11-16T10:58:33.199-06:00</updated><title type='text'>Some Intrepid notes</title><content type='html'>I figured I'd mention this in case other people have these problems (and solutions) and want to know if they're alone.&lt;br /&gt;&lt;br /&gt;So on my laptop, Dell Inspiron 6400, I went from Gutsy to Intrepid within a couple days. I tried Hardy very briefly. My Gutsy-&gt;Hardy upgrade was rocky, but Hardy-&gt;Intrepid was smooth as a baby's bottom.&lt;br /&gt;&lt;br /&gt;So, starting with Hardy, Sendmail takes about a minute to start. Though I'm told that it's because I never configured it. I never use it. So I uninstalled it. I don't even remember why I had it. BUT, it never did this under Gutsy.&lt;br /&gt;&lt;br /&gt;Starting with Intrepid, something related to dhclient takes about a minute, dare I say maybe two minutes, to start during my boot sequence. I'm working on resolving it at the moment. Pretty sad.&lt;br /&gt;&lt;br /&gt;Gnome doesn't have as many compiz bugs when starting up as I've had in Gutsy, but overall I feel like it takes longer before things are usable. Once it's up though, it's just fine. I think Firefox is faster, yay.&lt;br /&gt;&lt;br /&gt;Now, some of my run-on-startup program configs got wiped, I think going from Hardy-&gt;Intrepid. I hear this has something to do with Gnome sessions stuff. I never was in love with Gnome anyway, maybe it's time to switch. I'm intrigued by wmii, and all the cool kids in my LUG are using it, so I might have to try it if I want to still be cool. I tried running it once, just to see if it had a usable default. It didn't really, but it started up pretty much instantly. Sortof scary. Or maybe it's sortof scary how much useless garbage Gnome starts up. Thank God it's Linux and I have a choice.&lt;br /&gt;&lt;br /&gt;Also, I use &lt;a href=http://tilda.sourceforge.net&gt;Tilda&lt;/a&gt;. I don't have the package installed since I was doing some development on it. For some reason, twice now, my config got wiped just randomly; it went back to the default config. I'm going to guess it has something to do with the Hardy or Intrepid updates. This has never happened before, I wonder what's up.&lt;br /&gt;&lt;br /&gt;Now, wireless, that's delicious. I have:&lt;br /&gt;&lt;br /&gt;0b:00.0 Network controller: Broadcom Corporation BCM4311 802.11b/g WLAN (rev 01)&lt;br /&gt;&lt;br /&gt;It's been getting progressively better over the semi-year releases. But up to Gutsy, it was still flaky. When I started up, I would have to reload the driver before getting it to work (unless I waited a while before logging in. Hmm.) Anyway, none of that in Intrepid (probably Hardy, I never really gave it a spin, but I think that's when my new driver came in). It also connects to anything reasonable that I've thrown at it, things that I could only connect to after a struggle, at best, before. I can steal the nets from my apartment where I couldn't in Gutsy. The whole issue of "wireless sucks on Linux" seems to be history for my particular configuration. I know your mileage will probably vary.&lt;br /&gt;&lt;br /&gt;How did a quick rant become so long?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-4952203639414010726?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/4952203639414010726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=4952203639414010726' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/4952203639414010726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/4952203639414010726'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2008/11/some-intrepid-notes.html' title='Some Intrepid notes'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-3778732127165262181</id><published>2008-09-08T10:27:00.000-05:00</published><updated>2008-09-08T10:34:16.814-05:00</updated><title type='text'>Reversing lists and strings in python; third field in [] is for step</title><content type='html'>This is the simplest way to reverse a string or list in Python:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; "aoeu"[::-1]&lt;br /&gt;'ueoa'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I was about to say this was pretty shitty because it doesn't follow any sort of pattern, it seems to be a special thing just out of nowhere. But then I tried -2, and -3. Turns out the third field is for step.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; "aoeu"[::-1]&lt;br /&gt;'ueoa'&lt;br /&gt;&gt;&gt;&gt; "aoeu"[::-2]&lt;br /&gt;'uo'&lt;br /&gt;&gt;&gt;&gt; "aoeu"[::-3]&lt;br /&gt;'ua'&lt;br /&gt;&gt;&gt;&gt; "0123456789"[::]&lt;br /&gt;'0123456789'&lt;br /&gt;&gt;&gt;&gt; "0123456789"[::1]&lt;br /&gt;'0123456789'&lt;br /&gt;&gt;&gt;&gt; "0123456789"[::2]&lt;br /&gt;'02468'&lt;br /&gt;&gt;&gt;&gt; "0123456789"[::3]&lt;br /&gt;'0369'&lt;br /&gt;&gt;&gt;&gt; "0123456789"[::-1]&lt;br /&gt;'9876543210'&lt;br /&gt;&gt;&gt;&gt; "0123456789"[::-2]&lt;br /&gt;'97531'&lt;br /&gt;&gt;&gt;&gt; "0123456789"[::-3]&lt;br /&gt;'9630'&lt;br /&gt;&gt;&gt;&gt; "0123456789"[2:4:-1]&lt;br /&gt;''&lt;br /&gt;&gt;&gt;&gt; "0123456789"[4:2:-1]&lt;br /&gt;'43'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, with [4:10] it takes the 4th through 10th item in the list. With [4:10:2], it takes every other item from 4 to 10. With [4:10:3] it takes every third item, and so forth. With [4:10:-1], well it seems to do nothing, but with [10:4:-1] it takes every item from 4 through 10, but in reverse order. With [10:4:-2] it takes every other item in reverse order.&lt;br /&gt;&lt;br /&gt;The more you know. No rainbows please.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-3778732127165262181?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/3778732127165262181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=3778732127165262181' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/3778732127165262181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/3778732127165262181'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2008/09/reversing-lists-and-strings-in-python.html' title='Reversing lists and strings in python; third field in [] is for step'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-3472913075215846333</id><published>2008-02-11T14:52:00.000-06:00</published><updated>2008-02-11T15:36:56.024-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='feedgetter'/><category scheme='http://www.blogger.com/atom/ns#' term='release'/><title type='text'>Feed Getter</title><content type='html'>I've mentioned in a &lt;a href=http://ill-logic-tech.blogspot.com/2007/12/rss-gripes.html&gt;previous post&lt;/a&gt; an RSS aggregator that I'm working on. It's tentatively called Feed Getter. I'm putting it up now because it's usable, and it would be nice to get feedback from anyone that wants this kind of thing. Here's the pitch:&lt;br /&gt;&lt;br /&gt;I can't find any RSS aggregators that just save the files I ask for. I don't want a program to download and play my podcasts for me, I just want the files on my machine, where I ask them to be, so I can view and play them with my usual programs. I want it to be automated, I don't want an interface. This is especially useful for automated things, like a desktop background changer. If you agree, Feed Getter may be for you.&lt;br /&gt;&lt;br /&gt;Now, it's in early stages, but it gets your files for the most part. The biggest issues: a) It gets files again, even if you have them already. I do this because I'm not sure if files on your machine are incomplete or not, so I assume they're incomplete and get the whole thing over again. The solution is to write to a temp file, and do an atomic copy to the main file only when it's done. That way I'm sure that if it's in the main file, it's complete. This will probably be in version 0.2. b) It doesn't delete old files. Probably version 0.3.&lt;br /&gt;&lt;br /&gt;Now, at this point I don't run this as my main user, and I especially won't once I start deleting files, and you may consider doing the same. I want to make sure that my code regarding restricting file creation/deletion to certain paths is safe before I do. If you're interested in using this program, and you're experienced in path safety in python, maybe you could review my code.&lt;br /&gt;&lt;br /&gt;So &lt;b&gt;&lt;a href=http://orblivion.specialkevin.com/assorted/feedGetter.html&gt;Here it is&lt;/a&gt;&lt;/b&gt;. Check it out, 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/3916802132854520262-3472913075215846333?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/3472913075215846333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=3472913075215846333' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/3472913075215846333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/3472913075215846333'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2008/02/feed-getter.html' title='Feed Getter'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-6965204478686054734</id><published>2008-02-09T19:11:00.000-06:00</published><updated>2008-02-09T20:20:48.924-06:00</updated><title type='text'>Optional sections of your document using LaTex</title><content type='html'>If you're like me, you have more that you could put on your resume than you can fit. You have to cut it down to what's relevant, but sometimes the best things to put in differ based on who you're sending it to. So you have to make different versions of your resume. And then it turns out you need to reformat something in your basic info, and you have to change every version. If you used a word processor for this, you know how this could be a pain in the ass.&lt;br /&gt;&lt;br /&gt;This is why I liked the idea of LaTeX; it's technically a programming language. TeX is anyway. I could make one giant resume, and put a bunch of conditionals in there. Now, I figured out how to do this, and I think it's a hack, I'm not really sure how this language works and I don't really care to find out. Point is, this works.&lt;br /&gt;&lt;br /&gt;Here's an example. Let's say there's an internship that I did a while ago that I might not want to include in all versions of my resume. First, I define this variable at the top:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;\global\let\includeinternship\relax&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then I test if it's undefined:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        \ifx\includeinternship\undefined&lt;br /&gt;                \textbf{Internship}&lt;br /&gt;                \begin{itemize}&lt;br /&gt;                        \item Brought coffee to employees&lt;br /&gt;                        \item Sat around&lt;br /&gt;                        \item Oh one time my boss had me make a spreadsheet&lt;br /&gt;                \end{itemize}&lt;br /&gt;        \fi&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You defined it, so it won't show up. Sortof backwards, but it works. Again, it's a hack, and I'm too lazy to figure out how to do it right. So, to make it show up, comment out the definition:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;%\global\let\includeinternship\relax&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So you could put all the variables on top, and that's a lot more convenient than what you had before. But it could still be better. Lets say you have different versions of your resume.tex handy, with different variable settings. If you have to change some formatting or details in your resume, you're back where you started; you have to make the change in all versions of the file. So, you should have only one version of resume.tex, and include the file variables.sty:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;In resume.tex:&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;\usepackage{variables}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;In variables.sty, in the same directory:&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;%\global\let\includeinternship\relax&lt;br /&gt;\global\let\includecrappygpa\relax&lt;br /&gt;%\global\let\includemacaroniartproject\relax&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So now, you keep around multiple versions of variables.sty, with different combinations of variable definitions commented out. Any changes to your resume, you only have to do once. Now, what if you're updating your resume and you decide to add variables. Well, that's the downside. You would have to add it to all the variable files. But that's a lot better and more straightforward, in my opinion, than making a more complicated change to multiple versions of a whole resume file.&lt;br /&gt;&lt;br /&gt;At this point, you can make multiple versions of variables.sty, or you can make a quick change to variables.sty and make a new resume.pdf. With multiple versions, you still have to rename them to variables.sty to use them. So, you just put it in my resume generating script:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;cp $1 variables.sty&lt;br /&gt;pdflatex resume.tex&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course, you have to be careful not to have anything you want to keep in variables.sty, because the cp will overwrite it. Keep your actual work in different files that you pass to this script. For instance:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;./makeResume.sh version3.sty&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-6965204478686054734?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/6965204478686054734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=6965204478686054734' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/6965204478686054734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/6965204478686054734'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2008/02/optional-sections-of-your-document.html' title='Optional sections of your document using LaTex'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-4316107148968410217</id><published>2008-02-06T21:20:00.000-06:00</published><updated>2008-02-06T21:27:55.444-06:00</updated><title type='text'>Submitted For Your Approval</title><content type='html'>I talked about &lt;b&gt;Differential Equation Munchers&lt;/b&gt; a bit in my &lt;a href=http://ill-logic-tech.blogspot.com/2008/01/to-my-naysayers.html&gt;previous post&lt;/a&gt;. I decided that I'm not going to wait until the game is "presentable" before releasing it. So &lt;a href=http://orblivion.specialkevin.com/assorted/diffEqMunchers.html&gt;Here You Go.&lt;/a&gt; It's in a "fully functional" state, but it's not pretty. I did get around to at least stealing all the Muncher artwork from the original game, but the Troggles still look MS Paint quality. Let me know if you decide to try it out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-4316107148968410217?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/4316107148968410217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=4316107148968410217' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/4316107148968410217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/4316107148968410217'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2008/02/submitted-for-your-approval.html' title='Submitted For Your Approval'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-2368728622710418973</id><published>2008-01-07T11:19:00.000-06:00</published><updated>2008-01-07T14:08:18.399-06:00</updated><title type='text'>To My Naysayers</title><content type='html'>You know you you are. I have successfully created a way to generate examples of first and second order differential equations. A little backstory is in order I guess.&lt;br /&gt;&lt;br /&gt;I mentioned my game engine in an earlier post. At this point, it's far from done, but it's functional. I put that on hold to make my game demo, which uses what I have so far of the engine. Independent of all this, I had the idea to make a game called Differential Equation Munchers, a parody of the classic &lt;a href=http://en.wikipedia.org/wiki/Number_Munchers&gt;Number Munchers&lt;/a&gt;, which the lucky among us had a chance to play in our elementary school Apple labs. I've decided to use this opportunity and make this as my demo.&lt;br /&gt;&lt;br /&gt;In the original game, you're given a category of things, such as "Multiples of 4". You walk around the board and eat the numbers that fit into that category. But watch out for the Troggle! Troggles can come into the board and eat you, so avoid them. You also die if you eat a number not in the category. You win the level when you eat all the numbers in the category.&lt;br /&gt;&lt;br /&gt;For my version, the categories are related to differential equations. Which means that I have to somehow render differential equations. My thought was that I would generate them on the fly. Someone else suggested that I should have a table instead.  Supposedly, writing a generator would take too long. I didn't want to make a table, I said. Either I would have too small a pool of possible answers, or it would be a real pain in the ass making a huge table by hand in Gimp. Plus, come on, that's lame. Right?&lt;br /&gt;&lt;br /&gt;Well, this weekend, I made a generator for First and Second order differential equations. I decided that, yes, if my categories were things like &lt;i&gt;solutions to the differential equation y' = 5xy + 7&lt;/i&gt;, I may be facing way more work than I intended, because I would have to solve Dif Eq's on the fly. However, if it's just categories like &lt;i&gt;First Order Differential Equations&lt;/i&gt;, then it's a simple matter of generating an equation that happens to have a y' in it (and some other rules). My program doesn't have to have any notion of solving or understanding a differential equation, it's just a dumb image generator. Read 'em and weep:&lt;br /&gt;&lt;br /&gt;&lt;a href=http://orblivion.specialkevin.com/assorted/munchscreen.png&gt;&lt;img width=50% height=50% src=http://orblivion.specialkevin.com/assorted/munchscreen.png&gt;&lt;/a&gt;&lt;br /&gt;(click to embiggen)&lt;br /&gt;&lt;br /&gt;Granted, this is a simplified version of what I want ultimately. I can take more time to make generators for that stuff later. This is good enough for my demo. Also, for the more complicated stuff down the line, there is a Python library called &lt;a href=http://code.google.com/p/sympy/&gt;sympy&lt;/a&gt; that can help me manipulate algebraic expressions.&lt;br /&gt;&lt;br /&gt;Anyway, I'm happy about that. The game is in fact playable now. I have to add things like number of lives, score, splash screens, difficulty, etc. Then it'll be fully functional. Then I'd have to go clean up pictures (making the dif eq's more readable would be a good start). Also putting the original artwork in. Then I'll have to add more categories of equations. Then it'll be suitable for a demo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-2368728622710418973?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/2368728622710418973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=2368728622710418973' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/2368728622710418973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/2368728622710418973'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2008/01/to-my-naysayers.html' title='To My Naysayers'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-8130573823811171655</id><published>2007-12-27T13:32:00.000-06:00</published><updated>2007-12-27T14:13:43.278-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gripes'/><title type='text'>RSS gripes</title><content type='html'>I should have a gripes tag.&lt;br /&gt;&lt;br /&gt;I am working on an RSS aggregator. I want it to get files for me. That's all. Put them where I want them. Is that so much to ask? I think it is, so I had to do it myself. All the better, I can customize it a lot this way. (It's written in Python using &lt;a href=http://feedparser.org/&gt;feedparser&lt;/a&gt;, I will post it to this blog when I'm done, probably public domain.) I want it to download my music for immediate initiation to my library, videos too perhaps, images definitely (comics; probably for a desktop changer later), and also maybe text; not sure what for yet.&lt;br /&gt;&lt;br /&gt;So at this point I have it pretty much working. Some of the nice things I don't quite have yet; filtering for certain entries, deleting files, putting the timestamp in the filename to further prevent collisions, etc. But for now I can use it, and it made me happy. Until, xkcd gave me this:&lt;br /&gt;&lt;br /&gt;&lt;description&gt;&amp;lt;img src="http://imgs.xkcd.com/comics/blade_runner.png" title="Blade Runner: Classic, but incredibly slow." alt="Blade Runner: Classic, but incredibly slow." /&amp;gt;&lt;/description&gt;&lt;br /&gt;&lt;br /&gt;This, and the html page (linked from the feed), are the only reference to the actual png. No direct link, so I have to now parse this bit of html, or the link that the rss feed points to. No way am I going to make a custom bit of code just for some emo nerd comic. (the fanboys already made me irritated with this comic, so it's convenient) But, it turns out that &lt;a href=http://www.pbfcomics.com&gt;Perry Bible Fellowship&lt;/a&gt; does the same thing; the supposed image link is actually an html link to a page that contains the image. All the podcasts have direct links to the mp3 files; after all, podcast players like to have direct links. I guess there aren't enough, if any, comic readers yet.&lt;br /&gt;&lt;br /&gt;And this is worse than parsing the feed, because there's no standard place to look for the link within the HTML; it's different for every comic. And the HTML page is subject to change at any moment. At least there's a standard in RSS. Some RSS feeds may have stuff in non-standard places, but I made a very easy way to define a non-standard place to look for stuff*, and I don't think they'll move it. And XML parsing is less error prone that HTML.&lt;br /&gt;&lt;br /&gt;Well, fortunately there's a couple html parsers for Python, I'll probably use &lt;a href=http://wwwsearch.sourceforge.net/pullparser/&gt;pullparser&lt;/a&gt;. My hope now is that it's as easy as feedparser, and I can make my custom settings a similar way*. Though, there are bound to be multiple images in the html page, so I have to somehow identify the one I want. Perhaps by tag id, or maybe the directory that holds the image. God help me if I have to write regexes; I want this to be simple, it's weird enough that my configs are a list of dictionaries in Python.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;*Here's how I have it get files in non-standard fields. feedparser puts the whole feed xml file into a tree of dictionaries and lists. Within each entry, your podcast (for instance) item is usually at entry["enclosures"][0]["href"]. This is what I have as the default. But what if I wanted something at entry["link"][1]["href"] (semi-madeup example). My config file is written in Python too. I have a list of dictionaries that define each feed. To my dictionary I add "url-basis":["link", 1, "href"], and it knows to look at entry["link"][1]["href"]. It's very convenient that in Python you can say x[a], and it will try to treat x as a dictionary or list, depending on what type a is (and of course, throw an exception if you guessed wrong). &lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-8130573823811171655?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/8130573823811171655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=8130573823811171655' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/8130573823811171655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/8130573823811171655'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2007/12/rss-gripes.html' title='RSS gripes'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-5387653882294138567</id><published>2007-12-19T15:10:00.000-06:00</published><updated>2007-12-19T15:32:38.771-06:00</updated><title type='text'>Idea for an anti-phishing plugin</title><content type='html'>I just thought of a decent anti-phishing scheme, which would probably make a good plugin for Firefox. Particularly useful for those sites that use &lt;a href=http://www.msnbc.msn.com/id/8586332/&gt;unicode for evil.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The plugin would give you a button you can push that tells you if you're on one of a whitelist of sites. If you're not, and you thought you were, you're being phished. It would be tedious to whitelist every single site out there, of course. Mainly your important accounts (bank, paypal, email). Listing as many as 20 things sounds like it's worth my time for safety.&lt;br /&gt;&lt;br /&gt;Another variation: a small popup (not a dialog you have to click on), or maybe a change of color of a widget on your browser, that comes when you are on a whitelisted site. Sounds a bit backwards at first, but really, you can't get warned when you're on a phishing site unless you have a perfect blacklist (and if there were one, there would be no use for my plugin). My thought is, eventually you'll get used to seeing the popup every time you're at on of your important sites. Then, one day you go to a phishing site. Because of habit, you'll hopefully think that something is a little off when the popup doesn't show, and take notice. Unlike the first variation, I think this variation could work for general carelessness, not just the unicode trick. You would probably combine the two, really.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-5387653882294138567?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/5387653882294138567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=5387653882294138567' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/5387653882294138567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/5387653882294138567'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2007/12/idea-for-anti-phishing-plugin.html' title='Idea for an anti-phishing plugin'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-113045350796226336</id><published>2007-09-28T12:39:00.000-05:00</published><updated>2007-09-28T13:02:31.357-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><category scheme='http://www.blogger.com/atom/ns#' term='chat'/><title type='text'>And while I'm at it</title><content type='html'>I made a chat program in Visual Basic in college. It sucked as a program, but it had a neat feature I always wanted out of a chat client, which is multiple input windows. Here's an example:&lt;br /&gt;&lt;br /&gt;&lt;font color=green&gt;____________________________________&lt;br /&gt;&lt;b&gt;CoolGal27:&lt;/b&gt; Hey how's it going?&lt;br /&gt;&lt;b&gt;SmooveDood69:&lt;/b&gt; Not bad.&lt;br /&gt;____________________________________&lt;br /&gt;&lt;i&gt;Enter Message:&lt;/i&gt;&lt;br /&gt;&lt;small&gt;Actually, I was just getting done with my dissertation on bacteriophages. It's really quite fascinating, these virus-like agents actually attack bacteria, in a similar way to how viruses&lt;/small&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;font color=green&gt;____________________________________&lt;br /&gt;&lt;b&gt;CoolGal27:&lt;/b&gt; Hey how's it going?&lt;br /&gt;&lt;b&gt;SmooveDood69:&lt;/b&gt; Not bad.&lt;br /&gt;&lt;b&gt;CoolGal27:&lt;/b&gt; Want to meet up for dinner?&lt;br /&gt;____________________________________&lt;br /&gt;&lt;i&gt;Enter Message:&lt;/i&gt;&lt;br /&gt;&lt;small&gt;Actually, I was just getting done with my dissertation on bacteriophages. It's really quite fascinating, these virus-like agents actually attack bacteria, in a similar way to how viruses dangerous to you and me would attack our cells. My personal thesis focused on&lt;/small&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Goddammit! See, now I have to copy all this text, type in, "yeah sure, but I can't until 7", and paste my long discussion back into the input window.&lt;br /&gt;&lt;br /&gt;I'd make a plugin that would give you two or more input windows, so you could have that long thing you were typing along side the quick thing you send over.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Another idea I had was the ability to send a message to multiple people at once. Not in a chat room, just a quick message or two privately. As it stands, if there's a kool link ^_^ that I need all my friendz 2 see, I need to paste it into all the different windows, etc. I'd like to make a plugin that gives the ability to multicast messages.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And dammit why did 2.2 get rid of the font sweep-away icon?!? The greatest thing Pidgin ever did.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-113045350796226336?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/113045350796226336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=113045350796226336' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/113045350796226336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/113045350796226336'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2007/09/and-while-im-at-it.html' title='And while I&apos;m at it'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-6953470321071168145</id><published>2007-09-28T11:03:00.000-05:00</published><updated>2007-09-28T13:02:21.317-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><category scheme='http://www.blogger.com/atom/ns#' term='chat'/><title type='text'>Pidgin Gripes</title><content type='html'>I like Pidgin, it's straightforward, faster than AIM, etc. Last I checked (like 5 years ago or so) Trillian was slow as hell, though I don't use Windows at home anymore anyway. However there are a couple things that really annoy me about Pidgin, and sometimes IM clients in general, so I'm thinking of starting to make plugins to fix it. Kindof like I was going to make Tomboy plugins and still have yet to do. Here are my gripes:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Handling of Incorrect Passwords&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;First and FOREMOST, in any other interface I can think of, if I put in an incorrect password, the application informs me of the situation, and offers me another try. Not so with Pidgin. Maybe you never noticed because you save your password on your machine; that's not for me. (though a Keyring plugin would be super kosher). &lt;br /&gt;&lt;br /&gt;No, what it does (if I remember correctly) is inform me that my password is wrong, and offers me to "change my account settings", "connect" (with the &lt;i&gt;same&lt;/i&gt; wrong password, as if it'll work the second time), or just give up. Now, when I "modify my account", the bad password I just entered is in the password field. That password field is there for those that want to save the password on the disk. This worried me (since I don't want it on the disk) so I always deleted it from the field. Why was it trying to save my password when I told it not to, I wondered. Turns out that it wasn't actually going to save it, which is a bad interface choice. &lt;br /&gt;&lt;br /&gt;Anyway, you go ahead and modify it. Then you disable and enable the account and for whatever reason it still prompts you for a password, so that's how you try logging in again. Lame.&lt;br /&gt;&lt;br /&gt;Admittedly, with Pidgin 2.2 (which I just installed and which is strongly diffusing my argument here as I type it) it just says "Pidgin will not attempt to reconnect the account until you correct the error and re-enable the account.", and gives you a cancel button, which isn't much better but is less ironic at least. I still have to go to the menu and re-enable the account. That's much less annoying than it was before. But still, I shouldn't have to do even that, it's easy to make an immediate prompt.&lt;br /&gt;&lt;br /&gt;So, a plugin I would make would fix this, and give me a prompt to put in my password again, if I want.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Sending messages while away&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Remember when this was an optional feature, rather than the standard? I bet AIM still remembers this. I personally end up forgetting to take down my away message when I come back. People remind me. It makes the whole away message thing pointless, it should be up when I want people to think I'm away. Maybe some people don't forget, that's why it's a good option for them.&lt;br /&gt;&lt;br /&gt;Though, I still like it in theory. What I would do, and this is something that would solve a gripe with all chat clients, not just Pidgin, is make a plugin that would remind me every X minutes that I was away, if I was typing while away. For convenience, the dialogue would give me the option of coming back from away, too, and probably "don't bug me about it again this time" as well. That way, I could go away, send those few messages I forgot to send, go to lunch, come back, message Cezar, and he wouldn't have to remind me that my message still says I'm at lunch.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Away Messages Don't Expire&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Whereas the first gripe was with Pidgin and the second with IM clients in general, the third one is with myself. I forget or don't get around to changing my away message. I was apparently showering all day yesterday. What good does this sort of an away message paradigm do anybody? What I would make is the option to set an expiration time for an away message. I'd set an hour for the shower message. Then I would set a subsequent message. Like, work. Maybe I want another subsequent message (because when I get from work, I don't go and take myself off from away first I get home), this message would be a catch-all "At this point I'm not where I was when I last set my message, I can't tell you where I am, but I'm not at the computer, sorry" sort of message.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-6953470321071168145?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/6953470321071168145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=6953470321071168145' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/6953470321071168145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/6953470321071168145'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2007/09/pidign-gripes.html' title='Pidgin Gripes'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-8473373044304986271</id><published>2007-09-01T07:59:00.000-05:00</published><updated>2007-09-01T09:04:36.122-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='game demo'/><category scheme='http://www.blogger.com/atom/ns#' term='gnash'/><title type='text'>Game Demo Progress</title><content type='html'>I think I should post my progress as long as I have this Web Log and people are forced to listen by virtue of a feed associated with a certain User Group of a certain class of operating systems. I probably never mentioned this in the first place, but I've been commissioned (probably no money involved; I had a discussion with a friend, I'm pretty sure I can still technically say "commissioned") to make a 2D game engine.&lt;br /&gt;&lt;br /&gt;I initially chose C, with Python for scripting. Then I decided that for a prototype I should just do it in Python. Then I figured, why the hell not just make most of the actual product in Python? I would just use C for anything time intensive, such as looking for collisions ( O(N^2), unless there's some industry trick there that I have to learn ) and image effects (generated fire, as opposed to pre-animated fire).&lt;br /&gt;&lt;br /&gt;So far I've drafted up my requirements and cleared it with the guys planning the game itself. It was a decent sized doc too, I'm reasonably happy about getting that done. Next is code design, but it was pretty hard to think of how to design it without trying to code it first (a catch 22 of sorts), so I decided to make a prototype(/demo) to help give me the ideas. Turned out downright vital that I did this because things came up that I didn't anticipate at all, as I'm sure is always the case.&lt;br /&gt;&lt;br /&gt;For starters, I'm working on the Actor framework. Everything in this game is an actor. They send messages to each other, they have actions every frame, and then they draw. I'm not even worried about them showing themselves at this point, I'm mainly worried about laying out the code and making everything communicate properly. Input isn't really pressing either. I'll probably make a curses output module for starters, just for the heck of it, and just to show off (to myself, I guess) the modular nature (I hope) the engine will have. Actually, I'd mainly do it because it would help demonstrate that everything's working properly, and it's faster to get working than SDL, I would imagine.&lt;br /&gt;&lt;br /&gt;So I just got message passing going. I think next I'll put in a quick framework for input (but not bother implementing it yet), but soon go onto other important things like searching for collisions, etc.&lt;br /&gt;&lt;br /&gt;After this thing is done, or at least showing enough interesting aspects of my engine, I hope to have a presentation for this user group about game programming and Python. This would probably be my first presentation; I'm not used to doing them and it might be a while before I get around to that.&lt;br /&gt;&lt;br /&gt;In this post I'd also like to chime in and say I'm impressed that &lt;a href="http://www.gnu.org/software/gnash/"&gt;Gnash&lt;/a&gt; works on Youtube, at least on a rudimentary level. Not Google Video though, sadly. So now I won't have to bust my head, having a 64 bit system, until Gutsy comes out and I can easily use the nspluginwrapper (I went from a naive Windows user that would install programs in a semi-irresponsible manner to a naive Linux user that refuses to install anything not from an official repository). Heck I may just stick with gnash, I've heard that it uses Open GL, so it should be faster than Flash. I think it is, really, the load time for the YouTube app is damn near instantaneous, though my computer is fast. Maybe I'll run a little comparison.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-8473373044304986271?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/8473373044304986271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=8473373044304986271' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/8473373044304986271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/8473373044304986271'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2007/09/game-demo-progress.html' title='Game Demo Progress'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-8110106771254347910</id><published>2007-07-01T09:22:00.000-05:00</published><updated>2007-07-01T09:40:11.575-05:00</updated><title type='text'>Capitalism and Linux</title><content type='html'>I read Freddy Martinez's blog post about &lt;a href=http://admiralchicago.wordpress.com/2007/07/01/windows-how-we-bash-you/&gt;not bashing Windows&lt;/a&gt; and started writing a comment, and realized that it was much longer than his initial post, so I figured I'd just post it to my own blog, since I don't post here enough anyway.&lt;br /&gt;&lt;br /&gt;Like Freddy, I have capitalist ideals. When people were telling me about Linux a few years ago, I had the hardest time comprehending how a free operating system could even get off the ground. There are a couple things to consider.&lt;br /&gt;&lt;br /&gt;Firstly, I realized that free human interaction naturally and rightly includes both selfish competition as well as selfless collaboration. I've realized that the bottom line is freedom, not so much capitalism, if we are to define capitalism as selfish competition within a free market. (If you define capitalism just as a free market, that can also include the selfless collaboration if you think about it). So, people often get a lot of things done in the name of selfishness, as they're rewarded for their work with money. But people also can also accomplish a lot in a collaborative environment, something I was too naive to recognize back then. As much as human nature can be selfish and may often require capitalism to accomplish anything, there is also a nicer side of it. Remember that we have friends and families. As it is, capitalism and communism coexist peacefully, in a sense. (Yes I do consider free software somewhat of a a form of communism, and since there no regulations and nobody's forced to do anything it doesn't bother me). I heard a funny thing one day. A family should work like communism; from each according to his/her ability, to each according to his/her needs. Honestly, the only reason to hate communism is if it a) forces people into it (government imposed, particularly) or b) doesn't work. Free Software is free market communism, and so far it seems to work, and I think it's fantastic. Though, to be honest, I'm still pretty surprised it works as well as it does, but I think I'll grow to understand it eventually.&lt;br /&gt;&lt;br /&gt;Secondly, and hopefully not completely nullifying the first point, Linux does make money, and as long as it's Free to the users and developers, I'm pretty sure it even has Stallman's blessings. Think about this, there's a utility that company A and company B both want. They could both invest the effort to make it, or they could both spend half the resources to make it together. Now, as the tool improves over time, the companies will patch it. Would it make sense to keep the patch for themselves? Not so much, because they would then have to keep patching each new version as it came out. Might as well submit their patch so it gets included in new versions. They make the software freely available (rather than secret between their two companies) so that Companies  C and D come into the picture and start using and improving it further. Still, in a way this somewhat fits the communal view. I think it's similar to committees formed by multiple companies for their mutual benefit. (Yes the RIAA is a communist drone and must be stopped)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-8110106771254347910?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/8110106771254347910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=8110106771254347910' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/8110106771254347910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/8110106771254347910'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2007/07/capitalism-and-linux.html' title='Capitalism and Linux'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3916802132854520262.post-8126918818027376832</id><published>2007-06-30T19:09:00.000-05:00</published><updated>2007-06-30T20:16:43.391-05:00</updated><title type='text'>taking Simple Notetaking to ridiculous ends</title><content type='html'>Anybody that knows me well enough knows that I'm very slow to change my habits. When I feel comfortable with a certain process, I feel rather uncomfortable changing it. This is particularly true when it comes to using a convenient tool, God forbid that ti has a &lt;i&gt;GUI&lt;/i&gt;, that does a bunch of stuff for me. Instead, I do things in a very mundane and unsophisticated manner with the future (realistically far future if ever) intention to establish a more sophisticated system myself. I'd rather know everything my tools are doing, I want all interfaces to be transparent, so I can integrate everything as I want whenever I want. It's through those barriers that I broke to finally try Tomboy.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.gnome.org/projects/tomboy/"&gt;Tomboy&lt;/a&gt;, a Gnome app, is a pretty great tool on it's own if you're not crazy like me. It's a simple wiki-esque note taking system, automatically saves, nice keybindings and quick workflow (albeit with a few problems with key bindings, at least on my Dvorak keyboard). The big selling point is that you can make links to other notes by their name. Any text in any note (other than in the note's title) that is the name of another note automatically becomes a link to that note. It's a simplified Wiki with no "edit" screen, for a sped up work flow.&lt;br /&gt;&lt;br /&gt;It's good for my psychotic note taking practices, however I never tried it because I wanted a more integrated, database-based thing, where I could easily move note items around, generate lists as I want them, etc. I was using vim and text files until now (and have like 100 files left to manually import, thankfully I found a python script for &lt;a href="http://uwstopia.nl/files/2006/05/copy-to-clipboard"&gt;copying a file from standard input to the clipboard&lt;/a&gt;), figuring I could more easily import to whatever it is that I wrote more easily with text, but Tomboy uses XML so it's not too bad, even if I still ended up going that route.&lt;br /&gt;&lt;br /&gt;Fortunately my issues aren't too important anyway, because Tomboy has plugins. Herein lies the heart of this post. Now I can still make any sort of integration I want. It's nice because instead of starting from scratch and making some crappy program that'll end up losing all of my notes, I can start from something relatively stable and very convenient.&lt;br /&gt;&lt;br /&gt;Tomboy is written in &lt;a href="http://www.mono-project.com/Main_Page"&gt;Mono&lt;/a&gt;. It's pretty funny because the plugin files are .dll files. But it's still GTK. It was easy enough to &lt;a href=http://live.gnome.org/Tomboy/HowToCreatePlugins&gt;build a sample plugin&lt;/a&gt;. I envision myself making a ton of these before I'm done. I also hope to describe the API on this wiki page. At this point the only documentation is the code for the existing plugins.&lt;br /&gt;&lt;br /&gt;Why does a note taking program need plugins? Well, there are plugins available for integration with Evolution, Trac, and Gaim. Simple stuff like that which allow you type links that will activate things in those programs.&lt;br /&gt;&lt;br /&gt;I plan to do a couple like that, but hopefully I can eventually realize the whole of my note-taking psychosis. It would be nice to integrate it with some sort of calendar support. Some sort of automation of listing things in a certain class would be nice too. This is more database-esque behavior, so I may think about integrating it with some sort of database. Though the newest version apparently supports tagging, perhaps that's a good enough platform.&lt;br /&gt;&lt;br /&gt;I guess that's the end of it for now. I'll let you know when I make some plugins.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-8126918818027376832?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/8126918818027376832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=8126918818027376832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/8126918818027376832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/8126918818027376832'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2007/06/taking-simple-notetaking-to-ridiculous.html' title='taking Simple Notetaking to ridiculous ends'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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-3916802132854520262.post-1467682795699013833</id><published>2007-05-07T10:04:00.000-05:00</published><updated>2007-05-07T10:06:39.781-05:00</updated><title type='text'>This is my tech blog</title><content type='html'>This is where I will start posting about technical things that are on my mind. It will eventually be aggregated to www.chicagolug.org/planet/ with other members of the LUG.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3916802132854520262-1467682795699013833?l=ill-logic-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ill-logic-tech.blogspot.com/feeds/1467682795699013833/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3916802132854520262&amp;postID=1467682795699013833' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1467682795699013833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3916802132854520262/posts/default/1467682795699013833'/><link rel='alternate' type='text/html' href='http://ill-logic-tech.blogspot.com/2007/05/this-is-my-tech-blog.html' title='This is my tech blog'/><author><name>Dan</name><uri>http://www.blogger.com/profile/17464783227690703857</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>
