diff --git a/Elm.cabal b/Elm.cabal
--- a/Elm.cabal
+++ b/Elm.cabal
@@ -1,6 +1,6 @@
 
 Name:                Elm
-Version:             0.5.0.2
+Version:             0.6
 Synopsis:            The Elm language module.
 Description:         Elm aims to make client-side web-development more pleasant.
                      It is a statically/strongly typed, functional reactive
@@ -22,7 +22,7 @@
 Build-type:          Simple
 
 Extra-source-files:  changelog.txt
-Data-files:          elm-runtime-0.5.0.2.js
+Data-files:          elm-runtime-0.6.js
 Cabal-version:       >=1.8
 
 source-repository head
@@ -32,7 +32,7 @@
 Library
   exposed-modules:     Language.Elm,
                        Language.Elm.Quasi
-  Hs-Source-Dirs:      src, src/Parse, src/Types, src/Gen
+  Hs-Source-Dirs:      src, src/Gen
   other-modules:       Ast,
                        CompileToJS,
                        Cases,
@@ -43,17 +43,18 @@
                        Optimize,
                        Initialize,
                        Rename,
-                       Binops,
-                       Patterns,
-                       Parser,
-                       ParseLib,
-                       ParseExpr,
-                       ParseTypes,
-                       ParseModules,
-                       ParseForeign,
-                       Types,
+                       Parse.Binops,
+                       Parse.Expr,
+                       Parse.Foreign,
+                       Parse.Library,
+                       Parse.Modules,
+                       Parse.Parser,
+                       Parse.Patterns,
+                       Parse.Types,
+                       Types.Types,
                        Types.Constrain,
                        Types.Hints,
+                       Types.Solver,
                        Types.Substitutions,
                        Types.Unify,
                        Paths_Elm
@@ -69,13 +70,15 @@
                        text,
                        template-haskell,
                        shakespeare >= 1,
-                       pandoc <= 1.9.4.2,
+                       pandoc,
                        bytestring,
-                       hjsmin
+                       hjsmin,
+                       indents,
+                       filepath
 
 Executable elm
   Main-is:             Compiler.hs
-  Hs-Source-Dirs:      src, src/Parse, src/Types, src/Gen
+  Hs-Source-Dirs:      src, src/Gen
   other-modules:       Ast,
                        CompileToJS,
                        Cases,
@@ -86,17 +89,18 @@
                        Optimize,
                        Initialize,
                        Rename,
-                       Binops,
-                       Patterns,
-                       Parser,
-                       ParseLib,
-                       ParseExpr,
-                       ParseTypes,
-                       ParseModules,
-                       ParseForeign,
-                       Types,
+                       Parse.Binops,
+                       Parse.Expr,
+                       Parse.Foreign,
+                       Parse.Library,
+                       Parse.Modules,
+                       Parse.Parser,
+                       Parse.Patterns,
+                       Parse.Types,
+                       Types.Types,
                        Types.Constrain,
                        Types.Hints,
+                       Types.Solver,
                        Types.Substitutions,
                        Types.Unify,
                        Paths_Elm
@@ -110,6 +114,8 @@
                        blaze-markup == 0.5.1.*,
                        deepseq,
                        cmdargs,
-                       pandoc <= 1.9.4.2,
+                       pandoc,
                        bytestring,
-                       hjsmin
+                       hjsmin,
+                       indents,
+                       filepath
diff --git a/elm-runtime-0.5.0.2.js b/elm-runtime-0.5.0.2.js
deleted file mode 100644
--- a/elm-runtime-0.5.0.2.js
+++ /dev/null
@@ -1,123 +0,0 @@
-var Guid=function(){var d=0;return{guid:function(){return d+=1}}}(),Elm=Elm||{};
-Elm.JavaScript=function(){function d(a){for(var b=["Nil"],l=a.length;l--;)b=["Cons",a[l],b];return b}function a(a){for(var b=[];"Cons"===a[0];)b.push(a[1]),a=a[2];return b}function g(a){return a.slice(1)}function i(a){return["Tuple"+a.length].concat(a)}return{castJSBoolToBool:function(a){return a},castBoolToJSBool:function(a){return a},castJSNumberToFloat:function(a){return a},castFloatToJSNumber:function(a){return a},castJSNumberToInt:function(a){return~~a},castIntToJSNumber:function(a){return a},
-Experimental:{castJSElementToElement:function(a){return function(b){return function(l){return["Element",Guid.guid(),["EExternalHtml",l],a,b,1,Nothing,Nothing]}}},castElementToJSElement:function(a){return Render.render(a)}},castJSArrayToList:d,castListToJSArray:a,castJSStringToString:d,castStringToJSString:function(g){return"string"===typeof g?g:a(g).join("")},castTupleToJSTuple2:g,castTupleToJSTuple3:g,castTupleToJSTuple4:g,castTupleToJSTuple5:g,castJSTupleToTuple2:i,castJSTupleToTuple3:i,castJSTupleToTuple4:i,
-castJSTupleToTuple5:i}}();var Elm=Elm||{},JSjson=JSON;
-Elm.JSON=function(){function d(b,a){return function(h){return function(f){var c=i.castStringToJSString(h);return f[1].hasOwnProperty(c)&&(f=f[1][c],f[0]===b)?f[1]:a}}}function a(b){return function(a){function h(b){switch(b[0]){case "JsonNull":return null;case "JsonString":return i.castStringToJSString(b[1]);case "JsonObject":var c={},b=b[1][1],e;for(e in b)c[e]=h(b[e]);return c;case "JsonArray":c=i.castListToJSArray(b[1]);for(e=c.length;e--;)c[e]=h(c[e]);return c;default:return b[1]}}return JSjson.stringify(h(["JsonObject",
-a]),null,i.castStringToJSString(b))}}function g(b){function a(b){switch(typeof b){case "string":return["JsonString",i.castJSStringToString(b)];case "number":return["JsonNumber",i.castJSNumberToFloat(b)];case "boolean":return["JsonBool",i.castJSBoolToBool(b)];case "object":if(null===b)return["JsonNull"];for(var c in b)b[c]=a(b[c]);return b instanceof Array?["JsonArray",i.castJSArrayToList(b)]:["JsonObject",["JSON",b]]}}var b=JSjson.parse(b),h;for(h in b)b[h]=a(b[h]);return["JSON",b]}var i=Elm.JavaScript,
-j=["JSON",{}];return{empty:j,singleton:function(b){return function(a){var h={};h[i.castStringToJSString(b)]=a;return["JSON",h]}},insert:function(b){return function(a){return function(h){var h=h[1],f={},c;for(c in h)f[c]=h[c];f[i.castStringToJSString(b)]=a;return["JSON",f]}}},lookup:function(b){return function(a){var h=i.castStringToJSString(b);return a[1].hasOwnProperty(h)?Just(a[1][h]):Nothing}},findString:d("JsonString",["Nil"]),findObject:d("JsonObject",j),findArray:d("JsonArray",["Nil"]),findWithDefault:function(b){return function(a){return function(h){var f=
-i.castStringToJSString(a);return h[1].hasOwnProperty(f)?h[1][f]:b}}},remove:function(b){return function(a){var a=a[1],h={},f;for(f in a)h[f]=a[f];delete h[i.castStringToJSString(b)];return["JSON",h]}},toPrettyJSString:a,toJSString:a(""),fromJSString:g,toPrettyString:function(b){return function(g){return i.castJSStringToString(a(b)(g))}},toString:function(b){return i.castJSStringToString(a("")(b))},fromString:function(b){return g(i.castStringToJSString(b))},toList:function(b){var b=b[1],a=[],h;for(h in b)a.push(Value.Tuple(i.castJSStringToString(h),
-b[h]));return i.castJSArrayToList(a)},fromList:function(b){for(var b=i.castListToJSArray(b),a={},h=b.length;h--;)a[i.castStringToJSString(b[h][1])]=b[h][2];return["JSON",a]},JsonString:function(b){return["JsonString",b]},JsonNumber:function(b){return["JsonNumber",b]},JsonBool:function(b){return["JsonBool",b]},JsonNull:["JsonNull"],JsonArray:function(b){return["JsonArray",b]},JsonObject:function(b){return["JsonObject",b]}}}();
-var Value=function(){function d(b){if(0==b.length)return b;for(var b=b.replace(/"/g,"&#34;").replace(/'/g,"&#39;").replace(/</g,"&#60;").replace(/>/g,"&#62;").replace(/\n/g,"<br/>"),b=b.split("<br/>"),a=b.length;a--;){var h=b,f=a,c;c=b[a];if(0!=c.length){c=c.split("");" "==c[0]&&(c[0]="&nbsp;");for(var e=c.length;--e;)" "==c[e][0]&&" "==c[e-1]&&(c[e-1]+=c[e],c[e]="");for(e=c.length;e--;)if(1<c[e].length&&" "==c[e][0]){for(var n=c[e].split(""),g=n.length-2;0<=g;g-=2)n[g]="&nbsp;";c[e]=n.join("")}c=
-c.join("");c=" "===c[c.length-1]?c.slice(0,-1)+"&nbsp;":c}h[f]=c}return b.join("<br/>")}var a=function(b,g){if("object"===typeof b){if(b===g)return!0;if(b.length!==g.length)return!1;for(var h=b.length;h--;)if(!a(b[h],g[h]))return!1;return!0}return b===g},g=function(b){if("boolean"===typeof b)return b?"True":"False";if("number"!==typeof b){if("string"===typeof b&&2>b.length)return"'"+b+"'";if(b[0]){if("Tuple"===b[0].substring(0,5)){for(var a="",h=b.length;--h;)a=","+g(b[h])+a;","===a[0]&&(a=a.substring(1));
-return"("+a+")"}if("Cons"===b[0])for(var h="string"===typeof b[1]?'"':"]",f="string"===typeof b[1]?"":",",c="string"===typeof b[1]?function(c){return c}:g,a=("string"===typeof b[1]?'"':"[")+c(b[1]),b=b[2];;)if("Cons"===b[0])a+=f+c(b[1]),b=b[2];else return a+h;else{if("Nil"===b[0])return"[]";if("JSON"===b[0])return"(JSON.fromList "+g(Elm.JSON.toList(b))+")";if("RBNode"===b[0]||"RBEmpty"===b[0])return"(Map.fromList "+g(Elm.Dict.fold(function(c){return function(b){return function(a){return["Cons",["Tuple2",
-c,b],a]}}})(["Nil"])(b))+")";a="";for(h=b.length;--h;)a=" "+g(b[h])+a;a=b[0]+a;return 1<b.length?"("+a+")":a}}}return b+""},i=function(b){for(var a=["Nil"],h=b.length;h--;)a=["Cons",b[h],a];return a},j;j=document.addEventListener?function(b,a,h){b.addEventListener(a,h,!1)}:function(b,a,h){b.attachEvent("on"+a,h)};return{eq:a,str:i,show:function(b){return i(g(b))},Tuple:function(){var b=arguments.length,a=Array(b+1);for(a[0]="Tuple"+arguments.length;b--;)a[b+1]=arguments[b];return a},append:function(b,
-a){if("string"===typeof b&&"string"===typeof a)return b.concat(a);if("Nil"===b[0])return a;for(var h=["Cons",b[1],["Nil"]],f=h,b=b[2];"Cons"===b[0];)f[2]=["Cons",b[1],["Nil"]],b=b[2],f=f[2];f[2]=a;return h},listToArray:function(b){for(var a=[];"Cons"===b[0];)a.push(b[1]),b=b[2];return a},toText:function(b){if("string"===typeof b)return d(b);for(var a=[];"Cons"===b[0];)a.push(b[1]),b=b[2];return d(a.join(""))},properEscape:d,getTextSize:function(b,a,h){var f=document.createElement("div");f.innerHTML=
-h;f.style.textAlign="left";0<b&&(f.style.width=b+"px");f.style.visibility="hidden";f.style.styleFloat="left";f.style.cssFloat="left";document.body.appendChild(f);h=window.getComputedStyle(f);b=h.getPropertyValue("width").slice(0,-2)-0;h=h.getPropertyValue("height").slice(0,-2)-0;document.body.removeChild(f);delete f;return[Math.ceil(b),Math.ceil(Math.max(a,h))]},getSize:function(b){b=b.cloneNode(!0);b.style.visibility="hidden";b.style.styleFloat="left";b.style.cssFloat="left";document.body.appendChild(b);
-var a=b.offsetWidth,h=b.offsetHeight;document.body.removeChild(b);delete b;return[a,h]},getExcess:function(b){b=b.cloneNode(!0);b.style.visibility="hidden";b.style.styleFloat="left";b.style.cssFloat="left";document.body.appendChild(b);var a=b.offsetWidth,h=b.offsetHeight,f=window.getComputedStyle(b),c=f.getPropertyValue("width").slice(0,-2)-0,f=f.getPropertyValue("height").slice(0,-2)-0;document.body.removeChild(b);delete b;return[a-c,h-f]},groupForms:function(b){for(var b=Elm.JavaScript.castListToJSArray(b),
-a=[],h=[],f=b.length;f--;){var c=b[f];switch(c[4][0]){case "FElement":0<h.length&&(a.push(h),h=[]);a.push(c);break;default:h.push(c)}}0<h.length&&a.push(h);return a},wrap:function(a){var g=Value.getSize(a);return["Element",Guid.guid(),["EHtml",a],g[0],g[1],1,Nothing,Nothing]},addListener:j}}(),Elm=Elm||{};
-Elm.List=function(){function d(a){return function(b){if("Nil"===b[0])return b;"Cons"!==b[0]&&c("map");for(var e=["Cons",a(b[1]),["Nil"]],f=e,b=b[2];"Cons"===b[0];)f[2]=["Cons",a(b[1]),["Nil"]],b=b[2],f=f[2];return e}}function a(a){return function(b){return function(e){var f=b;if("Nil"===e[0])return f;for("Cons"!==e[0]&&c("foldl");"Cons"===e[0];)f=a(e[1])(f),e=e[2];return f}}}function g(a){return function(b){return function(e){var f=b;if("Nil"===e[0])return f;"Cons"!==e[0]&&c("foldr");for(var n=[];"Cons"===
-e[0];)n.push(e[1]),e=e[2];for(e=n.length;e--;)f=a(n[e])(f);return f}}}function i(c){return function(b){var e;"Cons"!==b[0]?e=void 0:(e=b[1],b=b[2],e=a(c)(e)(b));return e}}function j(b){return function(a){return function(e){if("Nil"===e[0])return["Cons",a,["Nil"]];"Cons"!==e[0]&&c("scanl");for(var f=[a];"Cons"===e[0];)a=b(e[1])(a),f.push(a),e=e[2];for(var e=["Nil"],n=f.length;n--;)e=["Cons",f[n],e];return e}}}function b(c){return function(a){a:{for(var e=[function(c){return"Nil"!==c[0]?void 0:["Tuple2",
-["Nil"],["Nil"]]},function(a){if("Cons"===a[0]){var e=a[1],a=a[2];var f=b(c)(a);"Tuple2"!==f[0]?e=void 0:(a=f[1],f=f[2],e=c(e)?["Tuple2",["Cons",e,a],f]:["Tuple2",a,["Cons",e,f]]);return e}}],f=e.length;f--;){var n=e[f](a);if(void 0!==n){a=n;break a}}a=void 0}return a}}function l(c){a:{for(var a=[function(c){return"Nil"!==c[0]?void 0:["Tuple2",["Nil"],["Nil"]]},function(c){if("Cons"!==c[0])c=void 0;else if(c=["Tuple2",c[1],l(c[2])],"Tuple2"!==c[0]||"Tuple2"!==c[1][0])c=void 0;else var a=c[1][1],b=
-c[1][2],c="Tuple2"!==c[2][0]?void 0:["Tuple2",["Cons",a,c[2][1]],["Cons",b,c[2][2]]];return c}],b=a.length;b--;){var e=a[b](c);if(void 0!==e){c=e;break a}}c=void 0}return c}function h(c){return function(a){a:{for(var b=[function(c){return"Nil"!==c[0]?void 0:["Nil"]},function(c){if("Cons"===c[0]){var a=c[1];return"Nil"!==c[2][0]?void 0:["Cons",a,["Nil"]]}},function(a){if("Cons"===a[0]){var b=a[1];if("Cons"===a[2][0]){var e=a[2][1],a=a[2][2];return["Cons",b,["Cons",c,h(c)(["Cons",e,a])]]}}}],e=b.length;e--;){var f=
-b[e](a);if(void 0!==f){a=f;break a}}a=void 0}return a}}function f(c){return function(a){a:{for(var b=[function(c){return"Nil"!==c[0]?void 0:["Nil"]},function(c){if("Cons"===c[0]){var a=c[1];return"Nil"!==c[2][0]?void 0:a}},function(a){if("Cons"===a[0]){var b=a[1];if("Cons"===a[2][0]){var e=a[2][1],a=a[2][2];return Value.append(b,Value.append(c,f(c)(["Cons",e,a])))}}}],e=b.length;e--;){var n=b[e](a);if(void 0!==n){a=n;break a}}a=void 0}return a}}var c=function(c){throw"Function '"+c+"' expecting a list!";
-},e=a(function(c){return function(a){return["Cons",c,a]}})(["Nil"]),n=g(function(c){return function(a){return Value.append(c,a)}})(["Nil"]),m=a(function(c){return function(a){return c&&a}})(!0),s=a(function(c){return function(a){return c||a}})(!1),p=a(function(c){return function(a){return c+a}})(0),k=a(function(c){return function(a){return c*a}})(1),u=i(function(c){return function(a){return Math.max(c,a)}}),x=i(function(c){return function(a){return Math.min(c,a)}});return{head:function(c){if("Cons"!==
-c[0])throw"Error: 'head' only accepts lists of length greater than one.";return c[1]},tail:function(c){if("Cons"!==c[0])throw"Error: 'tail' only accepts lists of length greater than one.";return c[2]},last:function(c){if("Cons"!==c[0])throw"Error: 'last' only accepts lists of length greater than one.";for(var a=c[1];"Cons"===c[0];)a=c[1],c=c[2];return a},map:d,foldl:a,foldr:g,foldl1:i,foldr1:function(a){return function(b){if("Nil"===b[0])throw"'foldr1' requires an non-empty list.";"Cons"!==b[0]&&
-c("foldr1");for(var e=[];"Cons"===b[0];)e.push(b[1]),b=b[2];for(var b=e.pop(),f=e.length;f--;)b=a(e[f])(b);return b}},scanl:j,scanl1:function(c){return function(a){if("Cons"!==a[0])throw"Error: 'scanl1' requires a list of at least length 1.";return j(c)(a[1])(a[2])}},filter:function(a){return function(b){if("Nil"===b[0])return b;"Cons"!==b[0]&&c("filter");for(var e=[];"Cons"===b[0];)a(b[1])&&e.push(b[1]),b=b[2];for(var b=["Nil"],f=e.length;f--;)b=["Cons",e[f],b];return b}},length:function(c){for(var a=
-0;"Cons"===c[0];)a+=1,c=c[2];return a},reverse:e,concat:n,concatMap:function(c){return function(a){return n(d(c)(a))}},and:m,or:s,all:function(c){return a(function(a){return function(b){return b&&c(a)}})(!0)},any:function(c){return a(function(a){return function(b){return b||c(a)}})(!1)},sum:p,product:k,maximum:u,minimum:x,partition:b,zipWith:function(a){return function(b){return function(e){if("Nil"===b[0]||"Nil"===e[0])return["Nil"];("Cons"!==b[0]||"Cons"!==e[0])&&c("zipWith");for(var f=[];"Cons"===
-b[0]&&"Cons"===e[0];)f.push(a(b[1])(e[1])),b=b[2],e=e[2];for(var e=["Nil"],n=f.length;n--;)e=["Cons",f[n],e];return e}}},zip:function(a){return function(b){if("Nil"===a[0]||"Nil"===b[0])return["Nil"];("Cons"!==a[0]||"Cons"!==b[0])&&c("zip");for(var e=[];"Cons"===a[0]&&"Cons"===b[0];)e.push(["Tuple2",a[1],b[1]]),a=a[2],b=b[2];for(var b=["Nil"],f=e.length;f--;)b=["Cons",e[f],b];return b}},unzip:l,intersperse:h,intercalate:f,sort:function(a){if("Nil"===a[0])return a;"Cons"!==a[0]&&c("sort");for(var b=
-[];"Cons"===a[0];)b.push(a[1]),a=a[2];b.sort(function(c,a){return c-a});for(var a=["Nil"],e=b.length;e--;)a=["Cons",b[e],a];return a},take:function(a){return function(b){if(0>=a)return["Nil"];if("Nil"===b[0])return b;"Cons"!==b[0]&&c("take");var e=["Cons",b[1],["Nil"]],f=e,b=b[2];for(--a;"Cons"===b[0]&&0<a;)f[2]=["Cons",b[1],["Nil"]],f=f[2],b=b[2],--a;return e}},drop:function(a){return function(b){if("Nil"===b[0])return b;for("Cons"!==b[0]&&c("drop");"Cons"===b[0]&&0<a;)b=b[2],--a;return b}}}}();
-Elm=Elm||{};
-Elm.Maybe=function(){function d(a){return function(d){return"Just"===a[0]?["Cons",a[1],d]:d}}function a(a){return function(d){return function(j){var b=a(d);return"Just"===b[0]?["Cons",b[1],j]:j}}}return{Just:function(a){return["Just",a]},Nothing:["Nothing"],catMaybes:Elm.List.foldr(d)(["Nil"]),isJust:function(a){return"Just"===a[0]},isNothing:function(a){return"Nothing"===a[0]},fromMaybe:function(a){return function(d){return"Just"===d[0]?d[1]:a}},consMaybe:d,mapMaybe:function(g){return Elm.List.foldr(a(g))(["Nil"])},maybe:function(a){return function(d){return function(j){return"Just"===
-j[0]?d(j[1]):a}}}}}();
-(function(){for(var d in Elm)this[d]=Elm[d];if(Elm.Dict)throw"Module name collision, 'Dict' is already defined.";Elm.Dict=function(){function a(a){return function(c){return function(b){return function(e){return function(f){return["RBNode",a,c,b,e,f]}}}}}function g(a){return function(){switch(a[0]){case "RBEmpty":return z(Value.str("(min RBEmpty) is not defined"));case "RBNode":switch(a[4][0]){case "RBEmpty":return["Tuple2",a[2],a[3]]}return g(a[4])}throw"Non-exhaustive pattern match in case";}()}
-function d(a){return function(c){var b;a:{switch(c[0]){case "RBEmpty":b=Nothing;break a;case "RBNode":b=function(){switch(compare(a)(c[2])[0]){case "EQ":return Just(c[3]);case "GT":return d(a)(c[5]);case "LT":return d(a)(c[4])}throw"Non-exhaustive pattern match in case";}();break a}throw"Non-exhaustive pattern match in case";}return b}}function j(a){return function(c){return function(b){var e;a:{switch(b[0]){case "RBEmpty":e=a;break a;case "RBNode":e=function(){switch(compare(c)(b[2])[0]){case "EQ":return b[3];
-case "GT":return j(a)(c)(b[5]);case "LT":return j(a)(c)(b[4])}throw"Non-exhaustive pattern match in case";}();break a}throw"Non-exhaustive pattern match in case";}return e}}}function b(a){return function(c){return A(d(a)(c))}}function l(c){a:{switch(c[0]){case "RBNode":switch(c[5][0]){case "RBNode":c=a(c[1])(c[5][2])(c[5][3])(a(w)(c[2])(c[3])(c[4])(c[5][4]))(c[5][5]);break a}}c=z(Value.str("rotateLeft of a node without enough children"))}return c}function h(c){a:{switch(c[0]){case "RBNode":switch(c[4][0]){case "RBNode":c=
-a(c[1])(c[4][2])(c[4][3])(c[4][4])(a(w)(c[2])(c[3])(c[4][5])(c[5]));break a}}c=z(Value.str("rotateRight of a node without enough children"))}return c}function f(c){a:{switch(c[0]){case "Black":c=w;break a;case "Red":c=C;break a}throw"Non-exhaustive pattern match in case";}return c}function c(c){a:{switch(c[0]){case "RBNode":switch(c[4][0]){case "RBNode":switch(c[5][0]){case "RBNode":c=a(f(c[1]))(c[2])(c[3])(a(f(c[4][1]))(c[4][2])(c[4][3])(c[4][4])(c[4][5]))(a(f(c[5][1]))(c[5][2])(c[5][3])(c[5][4])(c[5][5]));
-break a}}}c=z(Value.str("color_flip called on a RBEmpty or RBNode with a RBEmpty child"))}return c}function e(a){a:switch(a[0]){case "RBNode":switch(a[5][0]){case "RBNode":switch(a[5][1][0]){case "Red":a=l(a);break a}}}a:switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][1][0]){case "Red":switch(a[4][4][0]){case "RBNode":switch(a[4][4][1][0]){case "Red":a=h(a);break a}}}}}a:switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][1][0]){case "Red":switch(a[5][0]){case "RBNode":switch(a[5][1][0]){case "Red":a=
-c(a);break a}}}}}return a}function n(c){a:switch(c[0]){case "RBNode":switch(c[1][0]){case "Red":c=a(C)(c[2])(c[3])(c[4])(c[5]);break a}}return c}function m(c){return function(b){return function(f){var h=function(f){var n;a:{switch(f[0]){case "RBEmpty":n=a(w)(c)(b)(y)(y);break a;case "RBNode":n=function(){switch(compare(c)(f[2])[0]){case "EQ":return a(f[1])(f[2])(b)(f[4])(f[5]);case "GT":return a(f[1])(f[2])(f[3])(f[4])(h(f[5]));case "LT":return a(f[1])(f[2])(f[3])(h(f[4]))(f[5])}throw"Non-exhaustive pattern match in case";
-}();n=e(n);break a}throw"Non-exhaustive pattern match in case";}return n};return n(h(f))}}}function s(c){a:{switch(c[0]){case "RBNode":switch(c[4][0]){case "RBNode":switch(c[4][1][0]){case "Red":c=!0;break a}}}c=!1}return c}function p(c){a:{switch(c[0]){case "RBNode":switch(c[4][0]){case "RBNode":switch(c[4][4][0]){case "RBNode":switch(c[4][4][1][0]){case "Red":c=!0;break a}}}}c=!1}return c}function k(b){if(not(s(b))&&not(p(b))){b=c(b);a:switch(b[0]){case "RBNode":b:switch(b[5][0]){case "RBNode":switch(b[5][4][0]){case "RBNode":switch(b[5][4][1][0]){case "Red":b=
-c(l(a(b[1])(b[2])(b[3])(b[4])(h(b[5]))));break b}}}break a}}return b}function u(b){return function(f){var d;a:{switch(f[0]){case "RBEmpty":d=y;break a;case "RBNode":if("LT"===compare(b)(f[2])[0]){d=k(f);b:{switch(d[0]){case "RBEmpty":d=z(Value.str("delLT on RBEmpty"));break b;case "RBNode":d=e(a(d[1])(d[2])(d[3])(del(d[4]))(d[5]));break b}break}}else{f=s(f)?h(f):f;b:{switch(f[0]){case "RBNode":switch(f[5][0]){case "RBEmpty":f=eq(b,f[2]);break b}}f=!1}if(f)d=y;else{var f=not,i;b:{switch(d[0]){case "RBNode":switch(d[5][0]){case "RBNode":switch(d[5][1][0]){case "Red":i=
-!0;break b}}}i=!1}if(f=f(i)){f=not;b:{switch(d[0]){case "RBNode":switch(d[5][0]){case "RBNode":switch(d[5][4][0]){case "RBNode":switch(d[5][4][1][0]){case "Red":i=!0;break b}}}}i=!1}f=f(i)}f&&(d=c(d),d=p(d)?c(h(d)):d);b:{switch(d[0]){case "RBNode":f=eq(b,d[2]);break b}f=!1}if(f)b:{switch(d[0]){case "RBEmpty":d=z(Value.str("delEQ called on a RBEmpty"));break b;case "RBNode":i=g(d[5]);c:{switch(i[0]){case "Tuple2":f=i[1];break c}break}c:{switch(i[0]){case "Tuple2":i=i[2];break c}break}var f=a(d[1])(f)(i)(d[4]),
-j=function(c){a:{switch(c[0]){case "RBNode":switch(c[4][0]){case "RBEmpty":c=y;break a}}c=k(c);b:{switch(c[0]){case "RBEmpty":c=y;break b;case "RBNode":c=e(a(c[1])(c[2])(c[3])(j(c[4]))(c[5]));break b}throw"Non-exhaustive pattern match in case";}}return c};d=n(j(d[5]));d=e(f(d));break b}break}else b:{switch(d[0]){case "RBEmpty":d=z(Value.str("delGT called on a RBEmpty"));break b;case "RBNode":d=e(a(d[1])(d[2])(d[3])(d[4])(del(d[5])));break b}break}}}break a}throw"Non-exhaustive pattern match in case";
-}return n(d)}}function x(c){return function(b){a:{switch(b[0]){case "RBEmpty":b=y;break a;case "RBNode":b=a(b[1])(b[2])(c(b[3]))(x(c)(b[4]))(x(c)(b[5]));break a}throw"Non-exhaustive pattern match in case";}return b}}function q(c){return function(a){return function(b){a:{switch(b[0]){case "RBEmpty":b=a;break a;case "RBNode":b=q(c)(c(b[2])(b[3])(q(c)(a)(b[4])))(b[5]);break a}throw"Non-exhaustive pattern match in case";}return b}}}function r(c){return function(a){return function(b){a:{switch(b[0]){case "RBEmpty":b=
-a;break a;case "RBNode":b=r(c)(c(b[2])(b[3])(r(c)(a)(b[5])))(b[4]);break a}throw"Non-exhaustive pattern match in case";}return b}}}var t=[],v;for(v in Elm.Prelude)0<=t.indexOf(v)||(this[v]=Elm.Prelude[v]);var A=Elm.Maybe.isJust,w=["Red"],C=["Black"],y=["RBEmpty"],B=y,z=console.log;return{empty:B,lookup:d,findWithDefault:j,member:b,insert:m,singleton:function(c){return function(a){return m(c)(a)(y)}},remove:u,map:x,foldl:q,foldr:r,union:function(c){return function(a){return q(m)(a)(c)}},intersect:function(c){return function(a){return q(function(c){return function(e){return function(f){return b(c)(a)?
-m(c)(e)(f):f}}})(B)(c)}},diff:function(c){return function(a){return q(function(c){return function(){return function(a){return u(c)(a)}}})(c)(a)}},keys:function(c){return q(function(c){return function(){return function(a){return["Cons",c,a]}}})(["Nil"])(c)},values:function(c){return q(function(){return function(c){return function(a){return["Cons",c,a]}}})(["Nil"])(c)},toList:function(c){return q(function(c){return function(a){return function(b){return["Cons",["Tuple2",c,a],b]}}})(["Nil"])(c)},fromList:function(c){return List.foldl(uncurry(m))(B)(c)}}}()})();
-(function(){for(var d in Elm)this[d]=Elm[d];Elm.Set=function(){var a=[],d;for(d in Elm.Prelude)0<=a.indexOf(d)||(this[d]=Elm.Prelude[d]);a=Dict.empty;d=Dict.remove;var i=Dict.member,j=Dict.union,b=Dict.intersect,l=Dict.diff,h=Dict.keys,f=List.foldl(function(c){return function(a){return Dict.insert(c)(["Tuple0"])(a)}})(a);return{empty:a,singleton:function(c){return Dict.singleton(c)(["Tuple0"])},insert:function(c){return Dict.insert(c)(["Tuple0"])},remove:d,member:i,union:j,intersect:b,diff:l,toList:h,
-fromList:f,foldl:function(c){return Dict.foldl(function(a){return function(){return function(b){return c(a)(b)}}})},foldr:function(c){return Dict.foldr(function(a){return function(){return function(b){return c(a)(b)}}})},map:function(c){return function(a){a=h(a);return f(List.map(c)(a))}}}}()})();Elm=Elm||{};
-Elm.Char=function(){function d(a,b){return function(d){d=d.charCodeAt(0);return a<=d&&d<=b}}var a=d(48,57),g=d(97,102),i=d(65,70);return{fromCode:function(a){return String.fromCharCode(a)},toCode:function(a){return a.charCodeAt(0)},toUpper:function(a){return a.toUpperCase()},toLower:function(a){return a.toLowerCase()},toLocaleUpper:function(a){return a.toLocaleUpperCase()},toLocaleLower:function(a){return a.toLocaleLowerCase()},isLower:d(97,122),isUpper:d(65,90),isDigit:a,isOctDigit:d(48,55),isHexDigit:function(d){return a(d)||
-g(d)||i(d)}}}();Elm=Elm||{};
-Elm.Color=function(){return{rgba:function(d){return function(a){return function(g){return function(i){return["Color",d,a,g,i]}}}},rgb:function(d){return function(a){return function(g){return["Color",d,a,g,1]}}},red:["Color",255,0,0,1],green:["Color",0,255,0,1],blue:["Color",0,0,255,1],yellow:["Color",255,255,0,1],cyan:["Color",0,255,255,1],magenta:["Color",255,0,255,1],black:["Color",0,0,0,1],white:["Color",255,255,255,1],gray:["Color",128,128,128,1],grey:["Color",128,128,128,1],complement:function(d){var a,
-g=d[1]/255;a=d[2]/255;var i=d[3]/255,d=Math.max(g,a,i),j=Math.min(g,a,i),j=d-j,b=0;0===j?b=0:d===g?b=(a-i)/j%6:d===a?b=(i-g)/j+2:d===i&&(b=(g-a)/j+4);a=60*b;var g=d*(0===d?0:j/d),b=(a+180)%360/60,l=g*(1-Math.abs(b%2-1)),j=i=a=0;0<=b&&1>b?(a=g,i=l,j=0):1<=b&&2>b?(a=l,i=g,j=0):2<=b&&3>b?(a=0,i=g,j=l):3<=b&&4>b?(a=0,i=l,j=g):4<=b&&5>b?(a=l,i=0,j=g):5<=b&&6>b&&(a=g,i=0,j=l);d-=g;return["Color",Math.round(255*(a+d)),Math.round(255*(i+d)),Math.round(255*(j+d)),1]},extract:function(d){return 1===d[4]?"rgb("+
-d[1]+","+d[2]+","+d[3]+")":"rgba("+d[1]+","+d[2]+","+d[3]+","+d[4]+")"}}}();
-var Collage=function(){function d(a,c){var b=c.length-1;if(!(0>=b))for(a.moveTo(c[b][1],c[b][2]);b--;)a.lineTo(c[b][1],c[b][2])}function a(a,c,b,d){0===a.length&&(a=[8,4]);var h=d.length-1;if(!(0>=h)){var g=d[h][1],i=d[h][2],k=0,j=0,l=0,q=0,r=0,t=0,v=a.length,A=!0,w=a[0];for(c.moveTo(g,i);h--;){k=d[h][1];j=d[h][2];l=k-g;q=j-i;for(r=Math.sqrt(l*l+q*q);w<=r;)g+=l*w/r,i+=q*w/r,c[A?"lineTo":"moveTo"](g,i),l=k-g,q=j-i,r=Math.sqrt(l*l+q*q),A=!A,t=(t+1)%v,w=a[t];0<r&&(c[A?"lineTo":"moveTo"](k,j),w-=r);g=
-k;i=j}}c.strokeStyle=Elm.Color.extract(b);c.stroke()}function g(b,c,e,n,g){c.clearRect(0,0,e,n);for(e=g.length;e--;){var i=g[e],p=b,n=c,k=i[1],j=i[2],l=i[3][1],q=i[3][2],i=i[4];n.save();(0!==l||0!==q)&&n.translate(l,q);k!==~~k&&n.rotate(2*Math.PI*k);1!==j&&n.scale(j,j);n.beginPath();switch(i[0]){case "FLine":a:switch(p=n,k=i,i=k[3][1],k[1][0]){case "Solid":k=k[2];d(p,i);p.strokeStyle=Elm.Color.extract(k);p.stroke();break;case "Dotted":a([3,3],p,k[2],i);break a;case "Dashed":a([8,4],p,k[2],i);break a;
-case "Custom":a(k[1][1],p,k[2],i)}break;case "FShape":a:switch(l=p,j=n,p=i[1],k=i[2],i=i[3][1],p[0]){case "Filled":p=j;d(p,i);p.fillStyle=Elm.Color.extract(k);p.fill();break a;case "Outlined":p=j;d(p,i);p.strokeStyle=Elm.Color.extract(k);p.stroke();break a;case "Textured":k=l;p=p[1];l=new Image;l.src=h.castStringToJSString(p);l.onload=k;d(j,i);j.fillStyle=j.createPattern(l,"repeat");j.fill();break a;case "CustomOutline":a(p[1],j,k,i)}break;case "FImage":k=n,j=i[1],l=i[2],i=i[3],q=new Image,q.onload=
-p,q.src=h.castStringToJSString(i),k.drawImage(q,-j/2,-l/2,j,l)}n.restore()}}function i(a,c,b){var d=Render.newElement("canvas");d.style.width=~~a+"px";d.style.height=~~c+"px";d.style.display="block";d.width=~~a;d.height=~~c;if(d.getContext){var h=d.getContext("2d"),a=d.width,c=d.height;g(function(){g(this,h,a,c,b)},h,a,c,b);return d}d.innerHTML="Your browser does not support the canvas element.";return d}function j(a,c,b,d,h,i,g){var k=Render.render(g),b="translate("+(h-g[3]/2)+"px,"+(i-g[4]/2)+"px) "+
-(1===d?"":"scale("+d+","+d+")")+" "+(b===~~b?"":"rotate("+360*b+"deg)");k.style.transform=b;k.style.msTransform=b;k.style.MozTransform=b;k.style.webkitTransform=b;k.style.OTransform=b;b=Render.newElement("div");Render.addTo(b,k);b.style.width=~~a+"px";b.style.height=~~c+"px";b.style.overflow="hidden";return b}function b(a,c,b){if(!Value.eq(b,c)){var d=a.style.width.slice(0,-2)-0,h=a.style.height.slice(0,-2)-0;if("object"===typeof b[0]){if("object"===typeof c[0]&&a.getContext){var l=a.getContext("2d");
-return g(function(){g(this,l,d,h,b)},l,d,h,b)}c=i(d,h,b);c.style.position="absolute";return a.parentNode.replaceChild(c,a)}c=j(d,h,b[1],b[2],b[3][1],b[3][2],b[4][1]);c.style.position="absolute";return a.parentNode.replaceChild(c,a)}}function l(a,c,b,d,h){var i=0,g,k=(a[1]-d[1])/b,a=(a[2]-d[2])/b;0!==c&&(c*=-2*Math.PI,b=k*Math.cos(c)-a*Math.sin(c),a=k*Math.sin(c)+a*Math.cos(c),k=b);if(0===h.length)return!1;g=h[0];for(b=h.length-1;b--;){c=h[b];d=g[1];g=g[2];var j=c[1],l=c[2];if(g<l)var q=g,r=l;else q=
-l,r=g;if(d<j)var t=d,v=j;else t=j,v=d;q<a&&a<=r&&k<=v&&(k<=t||k<=(a-g)*(j-d)/(l-g)+d)&&++i;g=c}return 1===i%2}var h=Elm.JavaScript;return{collage:function(a,c,b){if(0===b.length)return i(a,c,[]);for(var d=Array(b.length),h=b.length;h--;){var g=b[h];d[h]="string"===typeof g[0]?j(a,c,g[1],g[2],g[3][1],g[3][2],g[4][1]):i(a,c,g)}return 1===b.length?d[0]:Render.flowWith(Render.goIn,function(c){return c},d)},updateCollage:function(a,c,e){if(1===e.length)return b(a,c[0],e[0]);for(var a=a.childNodes,d=a.length,
-h=d;h--;)b(a[d-h-1],c[h],e[h])},insideForm:function(a){return function(c){var b=a[1],d=a[2];if(6>c.length){var h=c[3][1],g=c[3][2],i=0,j=c[2];switch(c[4][0]){case "FShape":for(var u=c[4][3][1],x=u.length;--x;)var q=u[x],i=Math.max(i,q[1]*q[1]+q[2]*q[2]);i*=j*j;break;case "FImage":u=j*c[4][1]/2;j=j*c[4][2]/2;i=u*u+j*j;break;case "FElement":u=j*c[4][1][3]/2,j=j*c[4][1][4]/2,i=u*u+j*j}c.push(function(c,a){var b=c-h,e=a-g;return b*b+e*e<i+1})}if(!c[5](b,d))return!1;var r,t;switch(c[4][0]){case "FShape":return l(a,
-c[1],c[2],c[3],c[4][3][1]);case "FLine":return!1;case "FImage":r=c[4][1]/2;t=c[4][2]/2;break;case "FElement":r=c[4][1][3]/2,t=c[4][1][4]/2}return l(a,c[1],c[2],c[3],[[null,r,t],[null,-r,t],[null,-r,-t],[null,r,-t],[null,r,t]])}}}}(),Elm=Elm||{};
-Elm.Graphics=function(){function d(c){return function(a){return["Position",c,a]}}function a(c){return function(a){return["EText",c,a]}}function g(c){return function(a){return["EFlow",c,k.castListToJSArray(a)]}}function i(c){return["Line",k.castListToJSArray(c)]}function j(c){return function(a){var b=k.castListToJSArray(c);0<b.length&&b.push(b[0]);return["Shape",b,a]}}function b(c){return function(a){return function(b){return function(e){return["Form",c,a,b,e]}}}}function l(c){return function(a){return function(b){return["FLine",
-c,a,b]}}}function h(c){return function(a){return function(b){return["FShape",c,a,b]}}}function f(c,a,b,e,d,f){return["Element",Guid.guid(),c,a,b,e,d,f]}function c(c,a,b){return["Element",Guid.guid(),c,a,b,1,Nothing,Nothing]}function e(c){return~~c[3]}function n(c){return~~c[4]}function m(a){return function(b){return function(e){return c(["EImage",k.castStringToJSString(e)],a,b)}}}function s(a){return function(b){return c(A,a,b)}}function p(c){return function(a){return function(b){var e=map(function(b){return["Tuple2",
-c/2*cos(2*(pi/50)*b),a/2*sin(2*(pi/50)*b)]}),d=49,f=["Nil"];if(0<=d){do f=["Cons",d,f];while(0<d--)}return j(e(f))(b)}}}var k=Elm.JavaScript,u=["DRight"],x=["DDown"],q=["DOut"],r=["Near"],t=["Mid"],v=["Far"],A=["EEmpty"],w=["Solid"],C=["Dotted"],y=["Dashed"],B=["Filled"],z=["Outlined"],D=d(r)(r),E=d(v)(r),F=d(r)(v),G=d(v)(v),H=d(r)(t),I=d(v)(t),r=d(t)(r),v=d(t)(v),t=d(t)(t);return{left:["DLeft"],right:u,down:x,up:["DUp"],inward:["DIn"],outward:q,topLeft:D,topRight:E,bottomLeft:F,bottomRight:G,midLeft:H,
-midRight:I,midTop:r,midBottom:v,middle:t,middleAt:function(c){return function(a){return["PositionAt",c,a]}},topLeftAt:function(c){return function(a){return["PositionTL",c,a]}},topRightAt:function(c){return function(a){return["PositionTR",c,a]}},bottomLeftAt:function(c){return function(a){return["PositionBL",c,a]}},bottomRightAt:function(c){return function(a){return["PositionBR",c,a]}},absolute:function(c){return["Absolute",c]},relative:function(c){return["Relative",c]},width:function(c){return function(a){var b=
-a[2];switch(b[0]){case "EImage":case "EVideo":return f(a[2],c,a[4]*c/a[3],a[5],a[6],a[7]);case "EText":return b=Value.getTextSize(c,a[4],b[2]),f(a[2],c,b[1],a[5],a[6],a[7])}return f(a[2],c,a[4],a[5],a[6],a[7])}},height:function(a){return function(c){switch(c[2][0]){case "EImage":case "EVideo":return f(c[2],c[3]*a/c[4],a,c[5],c[6],c[7])}return f(c[2],c[3],a,c[5],c[6],c[7])}},size:function(c){return function(a){return function(b){return f(b[2],c,a,b[5],b[6],b[7])}}},opacity:function(c){return function(a){return f(a[2],
-a[3],a[4],c,a[6],a[7])}},color:function(c){return function(a){return f(a[2],a[3],a[4],a[5],Just(c),a[7])}},link:function(a){return function(c){return f(c[2],c[3],c[4],c[5],c[6],Just(k.castStringToJSString(a)))}},widthOf:e,heightOf:n,sizeOf:function(c){return["Tuple2",~~c[3],~~c[4]]},text:function(b){var e=Value.getTextSize(0,0,b);return c(a("left")(b),e[0],e[1])},asText:function(b){var b=monospace(Value.toText(Value.show(b))),e=Value.getTextSize(0,0,b);return c(a("left")(b),e[0],e[1])},plainText:function(b){var b=
-Value.toText(b),e=Value.getTextSize(0,0,b);return c(a("left")(b),e[0],e[1])},centeredText:function(b){var e=Value.getTextSize(0,0,b);return c(a("center")(b),e[0],e[1])},justifiedText:function(b){var e=Value.getTextSize(0,0,b);return c(a("justify")(b),e[0],e[1])},rightedText:function(b){var e=Value.getTextSize(0,0,b);return c(a("right")(b),e[0],e[1])},image:m,images:function(c){var a=Elm.Signal.constant(s(0)(0)),c=Elm.Signal.lift(function(c){var c=k.castStringToJSString(c),b=new Image;b.onload=function(){Dispatcher.notify(a.id,
-m(this.width)(this.height)(c))};b.src=c})(c);return Elm.Signal.lift2(function(c){return function(){return c}})(a)(c)},video:function(a){return function(b){return function(e){return c(["EVideo",k.castStringToJSString(e)],a,b)}}},fittedImage:function(a){return function(b){return function(e){return c(["EFittedImage",k.castStringToJSString(e)],a,b)}}},flow:function(a){return function(b){var d;d=map(e)(b);a:{switch(a[0]){case "DLeft":d=sum(d);break a;case "DRight":d=sum(d);break a}d=maximum(d)}var f;f=
-map(n)(b);a:{switch(a[0]){case "DDown":f=sum(f);break a;case "DUp":f=sum(f);break a}f=maximum(f)}return c(g(a)(b),d,f)}},above:function(a){return function(b){return c(g(x)(["Cons",a,["Cons",b,["Nil"]]]),max(~~a[3])(~~b[3]),~~a[4]+~~b[4])}},below:function(a){return function(b){return c(g(x)(["Cons",b,["Cons",a,["Nil"]]]),max(~~a[3])(~~b[3]),~~a[4]+~~b[4])}},beside:function(a){return function(b){return c(g(u)(["Cons",a,["Cons",b,["Nil"]]]),~~a[3]+~~b[3],max(~~a[4])(~~b[4]))}},layers:function(a){return c(g(q)(a),
-maximum(map(e)(a)),maximum(map(n)(a)))},collage:function(a){return function(b){return function(e){return c(["ECollage",a,b,Value.groupForms(e)],a,b)}}},spacer:s,container:function(a){return function(b){return function(e){return function(d){return c(["EContainer",e,d],a,b)}}}},line:i,segment:function(a){return function(c){return i(["Cons",a,["Cons",c,["Nil"]]])}},polygon:j,rect:function(a){return function(c){return function(b){return j(["Cons",["Tuple2",0-a/2,0-c/2],["Cons",["Tuple2",0-a/2,c/2],["Cons",
-["Tuple2",a/2,c/2],["Cons",["Tuple2",a/2,0-c/2],["Nil"]]]]])(b)}}},oval:p,circle:function(a){return p(2*a)(2*a)},ngon:function(a){return function(c){return function(b){var e=toFloat(a),d=map(function(a){return["Tuple2",c*cos(2*(pi/e)*a),c*sin(2*(pi/e)*a)]}),f=a-1,h=["Nil"];if(0<=f){do h=["Cons",f,h];while(0<f--)}return j(d(h))(b)}}},solid:function(a){return function(c){return b(0)(1)(["Tuple2",0,0])(l(w)(a)(c))}},dotted:function(a){return function(c){return b(0)(1)(["Tuple2",0,0])(l(C)(a)(c))}},dashed:function(a){return function(c){return b(0)(1)(["Tuple2",
-0,0])(l(y)(a)(c))}},customLine:function(a){return function(c){return function(e){return b(0)(1)(["Tuple2",0,0])(l(["Custom",k.castListToJSArray(a)])(c)(e))}}},filled:function(a){return function(c){return b(0)(1)(c[2])(h(B)(a)(c))}},outlined:function(a){return function(c){return b(0)(1)(c[2])(h(z)(a)(c))}},customOutline:function(a){return function(c){return function(e){return b(0)(1)(e[2])(h(["CustomOutline",k.castListToJSArray(a)])(c)(e))}}},textured:function(a){return function(c){return b(0)(1)(c[2])(h(["Textured",
-a])(null)(c))}},sprite:function(a){return function(c){return function(e){return function(d){return b(0)(1)(d)(["FImage",c,e,k.castStringToJSString(a)])}}}},toForm:function(a){return function(c){return b(0)(1)(a)(["FElement",c])}},rotate:function(a){return function(c){a:{switch(c[0]){case "Form":var e=c[2],d=c[3],f=c[4],c=b(a+c[1])(e)(d)(f);break a}throw"Non-exhaustive pattern match in case";}return c}},scale:function(a){return function(c){return b(c[1])(a*c[2])(c[3])(c[4])}},move:function(a){return function(c){return function(e){var d;
-a:{switch(e[0]){case "Form":d=e[1];var f=e[2],h=e[3],e=e[4];switch(h[0]){case "Tuple2":var g=h[1],h=h[2];d=b(d)(f)(["Tuple2",a+g,c+h])(e);break a}}throw"Non-exhaustive pattern match in case";}return d}}},isWithin:Collage.insideForm}}();Elm=Elm||{};
-Elm.Text=function(){function d(a){return Value.toText(a)}var a=function(a){return function(b){return"<"+a+' style="padding:0;margin:0">'+b+"</"+a+">"}},g=function(a,b){return function(d){return"<span style='"+a+":"+b+"'>"+d+"</span>"}},i=function(a){a=Elm.JavaScript.castStringToJSString(a);return g("font-family",a)},j=a("h1"),b=g("font-style","italic"),a=a("b"),l=g("text-decoration","underline"),h=g("text-decoration","overline"),f=g("text-decoration","line-through");return{fromString:d,toText:d,header:j,
-height:function(a){return g("font-size",a+"em")},italic:b,bold:a,underline:l,overline:h,strikeThrough:f,monospace:i("monospace"),typeface:i,color:function(a){return g("color",Elm.Color.extract(a))},link:function(a){return function(b){return"<a href='"+d(a)+"'>"+b+"</a>"}}}}();
-var Render=function(){function d(a){a=document.createElement(a);a.style.padding="0";a.style.margin="0";return a}function a(a){return a}function g(a){a.style.styleFloat="left";a.style.cssFloat="left";return a}function i(a){a.style.position="absolute";return a}function j(a,b,f){for(var h=d("div"),g=f.length;g--;){var i=a(b(f[g]));h.appendChild(i)}return h}function b(a){switch(a[0]){case "Absolute":return a[1]+"px";case "Relative":return 100*a[1]+"%"}}function l(a,e){e.style.position="absolute";e.style.margin=
-"auto";switch(a[0]){case "Position":"Far"!==a[1][0]&&(e.style.left=0);"Near"!==a[1][0]&&(e.style.right=0);"Far"!==a[2][0]&&(e.style.top=0);"Near"!==a[2][0]&&(e.style.bottom=0);break;case "PositionAt":e.style.top=b(a[2]);e.style.left=b(a[1]);var d="translate("+-elem[3]/2+"px,"+-elem[4]/2+"px)";e.style.transform=d;e.style.msTransform=d;e.style.MozTransform=d;e.style.webkitTransform=d;e.style.OTransform=d;break;default:d=a[0].slice(-2),e.style["T"===d[0]?"top":"bottom"]=b(a[2]),e.style["L"===d[1]?"left":
-"right"]=b(a[1])}}function h(c){var b={};switch(c[2][0]){case "EText":var b=c[2][1],f=c[2][2],m=d("div");m.innerHTML=f;m.style.textAlign=b;b=m;break;case "EImage":b=c[2][1];f=d("img");f.src=b;f.name=b;f.style.display="block";b=f;break;case "EVideo":m=c[2][1];b=d("video");b.controls="controls";f=d("source");f.src=m;m=m.split(".");f.type="video/"+m[m.length-1];b.appendChild(f);b.style.display="block";break;case "EFittedImage":var s=c[3],p=c[4],b=c[2][1],k=d("canvas");k.style.display="block";k.style.width=
-s+"px";k.style.height=p+"px";k.width=s;k.height=p;k.innerHTML="Your browser does not support the canvas element.";var u=d("img");u.onload=function(){if(k.getContext){var a=k.getContext("2d"),b=0,c=0,d=this.width,f=this.height;s/p>this.width/this.height?(f=this.width*p/s,c=(this.height-f)/2):(d=this.height*s/p,b=(this.width-d)/2);a.drawImage(u,b,c,d,f,0,0,k.width,k.height)}};u.src=b;b=k;break;case "EFlow":a:{b=c[2][2];switch(c[2][1][0]){case "DDown":b=b.slice(0).reverse();case "DUp":b=j(a,h,b);break a;
-case "DRight":b=b.slice(0).reverse();case "DLeft":b=j(g,h,b);break a;case "DOut":b=b.slice(0).reverse();case "DIn":b=j(i,h,b);break a}b=void 0}break;case "ECollage":b=Collage.collage(c[2][1],c[2][2],c[2][3]);break;case "EEmpty":b=d("div");break;case "EContainer":f=c[2][1];b=h(c[2][2]);l(f,b);f=d("div");f.style.position="relative";f.style.overflow="hidden";f.appendChild(b);b=f;break;case "EHtml":b=c[2][1];"button"!==b.type&&(f=Value.getExcess(b),c[3]-=f[0],c[4]-=f[1]);break;case "EExternalHtml":b=
-d("div"),b.appendChild(c[2][1])}b.id=c[1];b.style.width=~~c[3]+"px";b.style.height=~~c[4]+"px";1!==c[5]&&(b.style.opacity=c[5]);"Just"===c[6][0]&&(b.style.backgroundColor=Elm.Color.extract(c[6][1]));return"Just"===c[7][0]?(f=d("a"),f.href=c[7][1],f.appendChild(b),f):b}function f(b,d,j){"A"===b.tagName&&(b=b.firstChild);if(d[1]!==j[1]){if(d[2][0]!==j[2][0])return b.parentNode.replaceChild(h(j),b);var m=j[2],s=d[2];switch(m[0]){case "EText":m[1]!==s[1]&&(b.style.textAlign=m[1]);m[2]!==s[2]&&(b.innerHTML=
-m[2]);break;case "EImage":m[1]!==s[1]&&(b.src=m[1]);break;case "EVideo":case "EFittedImage":if(!Value.eq(m,s)||j[3]!==d[3]||j[4]!==d[4])return b.parentNode.replaceChild(h(j),b);break;case "ECollage":if(m[1]!==s[1]||m[2]!==s[2]||m[3].length!==s[3].length)return b.parentNode.replaceChild(h(j),b);Collage.updateCollage(b,s[3],m[3]);break;case "EFlow":if(m[1]!==s[1])return b.parentNode.replaceChild(h(j),b);var p=m[2],k=b.childNodes;if(p.length!==k.length)return b.parentNode.replaceChild(h(j),b);var s=
-s[2],u={};switch(m[1][0]){case "DDown":case "DUp":u=a;break;case "DRight":case "DLeft":u=g;break;case "DOut":case "DIn":u=i}for(m=k.length;m--;)f(k[m],s[m],p[m]),u(k[m]);break;case "EContainer":f(b.childNodes[0],s[2],m[2]);l(m[1],b.childNodes[0]);break;case "EHtml":j[1]!==d[1]&&(p=h(j),b.parentNode.replaceChild(p,b),b=p);"button"!==p.type&&(m=Value.getExcess(b),j[3]-=m[0],j[4]-=m[1]);break;case "EExternalHtml":j[1]!==d[1]&&b.parentNode.replaceChild(h(j),b)}j[3]!==d[3]&&(b.style.width=~~j[3]+"px");
-j[4]!==d[4]&&(b.style.height=~~j[4]+"px");j[5]!==d[5]&&(b.style.opacity=j[5]);2===j[6].length&&(m=Elm.Color.extract(j[6][1]),m!==b.style.backgroundColor&&(b.style.backgroundColor=m));if(2===j[7].length&&(1===d[7].length||j[7][1]!==d[7][1]))b.parentNode.href=j[7][1];j[1]=d[1]}}return{render:h,update:f,addTo:function(a,b){a.appendChild(b)},newElement:d,flowWith:j,goIn:i}}(),Elm=Elm||{};
-Elm.Signal=function(){var d=function(a,b,d){for(var h=a.kids,g=h.length;g--;)h[g].recv(b,d,a.id)},a=function(a){this.id=Guid.guid();this.value=a;this.kids=[];this.defaultNumberOfKids=0;this.recv=function(a,b,f){if(b=b===this.id)this.value=f;d(this,a,b);return b};Dispatcher.inputs.push(this)},g=function(a,b){this.id=Guid.guid();this.value=null;this.kids=[];this.count=0;this.changed=!1;b.reverse();this.recalc=function(){for(var d=a,e=b.length;e--;)d=d(b[e].value);this.value=d};this.recalc();this.recv=
-function(a,f){this.count+=1;f&&(this.changed=!0);this.count==b.length&&(this.changed&&this.recalc(),d(this,a,this.changed),this.changed=!1,this.count=0)};for(var e=b.length;e--;)b[e].kids.push(this)},i=function(a,b,e,h){this.id=Guid.guid();this.value=e?b(h.value):b;this.kids=[];this.recv=function(b,c){c&&(this.value=a(h.value)(this.value));d(this,b,c)};h.kids.push(this)},j=function(a,b,e){this.id=Guid.guid();this.value=a(e.value)?b:e.value;this.kids=[];this.recv=function(b,c){var h=c&&!a(e.value);
-h&&(this.value=e.value);d(this,b,h)};e.kids.push(this)},b=function(a){this.id=Guid.guid();this.value=a.value;this.kids=[];this.recv=function(b,e){var h=e&&!eq(this.value,a.value);h&&(this.value=a.value);d(this,b,h)};a.kids.push(this)},l=function(a){return function(b){return function(d){d=new g(function(a){return function(b){return[a,b]}},[a,d]);d=new j(function(a){return a[0]},[!0,b],d);return new g(function(a){return a[1]},[d])}}},h=function(a,b){this.id=Guid.guid();this.value=b.value;this.kids=
-[];this.count=0;this.changed=!1;this.recv=function(e,h,g){g===a.id&&(this.changed=h);this.count+=1;2==this.count&&(this.changed&&(this.value=b.value),d(this,e,this.changed),this.count=0,this.changed=!1)};a.kids.push(this);b.kids.push(this)};return{constant:function(b){return new a(b)},lift:function(a){return function(b){return new g(a,[b])}},lift2:function(a){return function(b){return function(d){return new g(a,[b,d])}}},lift3:function(a){return function(b){return function(d){return function(h){return new g(a,
-[b,d,h])}}}},lift4:function(a){return function(b){return function(d){return function(h){return function(i){return new g(a,[b,d,h,i])}}}}},foldp:function(a){return function(b){return function(d){return new i(a,b,!1,d)}}},foldp_:function(a){return function(b){return function(d){return new i(a,b,!0,d)}}},foldp1:function(a){return function(b){return new i(a,function(a){return a},!0,b)}},count:function(a){return new i(function(){return function(a){return a+1}},0,!1,a)},keepIf:function(a){return function(b){return function(d){return new j(function(b){return!a(b)},
-b,d)}}},dropIf:function(a){return function(b){return function(d){return new j(a,b,d)}}},keepWhen:function(a){return l(new g(function(a){return!a},[a]))},dropWhen:l,dropRepeats:function(a){return new b(a)},sampleOn:function(a){return function(b){return new h(a,b)}}}}();
-var Dispatcher=function(){function d(a){if(!a.hasOwnProperty("defaultNumberOfKids"))return!0;var g=a.kids.length;if(0==g)return!1;if(g>a.defaultNumberOfKids)return!0;for(var h=!1;g--;)h=h||d(a.kids[g]);return h}var a=null,g=0,i=[],j=null;return{initialize:function(){a=Elm.main();a.hasOwnProperty("recv")||(a=Elm.Signal.constant(a));j=a.value;for(var b=[],g=i.length;g--;)d(i[g])&&b.push(i[g]);i=b;document.getElementById("content").appendChild(Render.render(j));b=document.getElementById("widthChecker").offsetWidth;
-b!==window.innerWidth&&Dispatcher.notify(Window.dimensions.id,Value.Tuple(b,window.innerHeight));a=Elm.Signal.lift(function(a){var b=document.getElementById("content");Render.update(b.firstChild,j,a);return j=a})(a)},notify:function(a,d){g+=1;for(var h=!1,f=i.length;f--;)h=i[f].recv(g,a,d)||h;return h},inputs:i}}();
-Elm.HTTP=function(){function d(a){return function(d){return function(c){return function(e){return{"0":"Request",length:1,verb:b.castStringToJSString(a),url:b.castStringToJSString(d),data:null===c?null:b.castStringToJSString(c),headers:e}}}}}function a(a){return d("GET")(a)(null)(["Nil"])}function g(a,d){return function(c){if(""!==c.url){var e={value:["Waiting"]};a.push(e);var g=null;window.ActiveXObject&&(g=new ActiveXObject("Microsoft.XMLHTTP"));window.XMLHttpRequest&&(g=new XMLHttpRequest);g.onreadystatechange=
-function(){4===g.readyState&&(e.value=200===g.status?["Success",l(g.responseText)]:["Failure",g.status,l(g.statusText)],setTimeout(function(){i(a,d)},0))};g.open(c.verb,c.url,!0);Elm.List.map(function(a){g.setRequestHeader(b.castStringToJSString(a[1]),b.castStringToJSString(a[2]))})(c.headers);g.send(c.data)}}}function i(a,b){0<a.length&&(Dispatcher.notify(b.id,a[0].value),"Waiting"!==a[0].value[0]&&(a.shift(),setTimeout(function(){i(a,b)},0)))}function j(a){var b=Elm.Signal.constant(["Waiting"]),
-a=Elm.Signal.lift(g([],b))(a);return Elm.Signal.lift2(function(a){return function(){return a}})(b)(a)}var b=Elm.JavaScript,l=Elm.JavaScript.castJSStringToString;return{get:a,post:function(a){return function(b){return d("POST")(a)(b)(["Nil"])}},request:d,send:j,sendGet:function(b){return j(Elm.Signal.lift(a)(b))}}}();
-Elm.Input=function(){var d=Elm.JavaScript,a=Elm.JavaScript.castJSStringToString,g=function(b,g){b.placeholder=d.castStringToJSString(g);var h=Elm.Signal.constant(["Nil"]);Value.addListener(b,"keyup",function(){Dispatcher.notify(h.id,a(b.value));b.focus()});b.style.padding="1px";return Value.Tuple(Value.wrap(b),h)},i=function(a){a=document.createElement(a);a.style.padding="0";a.style.margin="0";return a},j=function(a){for(var d=i("select"),g=[];"Cons"===a[0];){var f=i("option"),c=Value.toText(a[1][1]);
-f.value=c;f.innerHTML=c;d.appendChild(f);g.push(a[1][2]);a=a[2]}var e=Elm.Signal.constant(g[0]);Value.addListener(d,"change",function(){Dispatcher.notify(e.id,g[d.selectedIndex])});return Value.Tuple(Value.wrap(d),e)};return{textArea:function(a){return function(d){var h=i("textarea");h.rows=d;h.cols=a;return g(h,"")}},textField:function(a){var d=i("input");d.type="text";return g(d,a)},password:function(a){var d=i("input");d.type="password";return g(d,a)},checkbox:function(a){var d=i("input");d.type=
-"checkbox";d.checked=a;var g=Elm.Signal.constant(a);Value.addListener(d,"change",function(){Dispatcher.notify(g.id,d.checked)});return Value.Tuple(Value.wrap(d),g)},dropDown:j,stringDropDown:function(a){return j(Elm.List.map(function(a){return Value.Tuple(a,a)})(a))},button:function(a){var g=i("input");g.type="button";g.value=d.castStringToJSString(a);var h=Elm.Signal.constant(!1);Value.addListener(g,"click",function(){Dispatcher.notify(h.id,!0);Dispatcher.notify(h.id,!1)});return Value.Tuple(Value.wrap(g),
-h)}}}();
-Elm.Keyboard={Raw:function(){function d(a,g){return"Nil"===g[0]?g:g[1]===a?g[2]:["Cons",g[1],d(a,g[2])]}var a=Elm.Signal.constant(["Nil"]),g=Elm.Signal.constant(["Nothing"]);Value.addListener(document,"keydown",function(d){var g;a:{for(g=a.value;"Nil"!==g[0];){if(g[1]===d.keyCode){g=!0;break a}g=g[2]}g=!1}g||Dispatcher.notify(a.id,["Cons",d.keyCode,a.value])||this.removeEventListener("keydown",arguments.callee,!1)});Value.addListener(document,"keyup",function(g){var j=d(g.keyCode,a.value);Dispatcher.notify(a.id,
-j)||this.removeEventListener("keyup",arguments.callee,!1)});Value.addListener(window,"blur",function(d){Dispatcher.notify(a.id,["Nil"])||this.removeEventListener("blur",arguments.callee,!1)});Value.addListener(document,"keypress",function(a){var d=Dispatcher.notify(g.id,["Just",a.charCode||a.keyCode]);Dispatcher.notify(g.id,["Nothing"]);d||this.removeEventListener("keypress",arguments.callee,!1)});return{keysDown:a,charPressed:g}}()};
-Elm.Mouse=function(){function d(a){var b=0,c=0;a||(a=window.event);if(a.pageX||a.pageY)b=a.pageX,c=a.pageY;else if(a.clientX||a.clientY)b=a.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,c=a.clientY+document.body.scrollTop+document.documentElement.scrollTop;return Value.Tuple(b,c)}var a=Elm.Signal.constant(Value.Tuple(0,0));a.defaultNumberOfKids=2;var g=Elm.Signal.lift(function(a){return a[1]})(a);g.defaultNumberOfKids=0;var i=Elm.Signal.lift(function(a){return a[2]})(a);i.defaultNumberOfKids=
-0;var j=Elm.Signal.constant(!1),b=Elm.Signal.constant(!1),l=Elm.Signal.constant(Value.Tuple());Value.addListener(document,"click",function(a){var d=Dispatcher.notify(b.id,!0),c=Dispatcher.notify(l.id,Value.Tuple());Dispatcher.notify(b.id,!1);!d&&!c&&this.removeEventListener("click",arguments.callee,!1)});Value.addListener(document,"mousedown",function(a){Dispatcher.notify(j.id,!0)||this.removeEventListener("mousedown",arguments.callee,!1)});Value.addListener(document,"mouseup",function(a){Dispatcher.notify(j.id,
-!1)||this.removeEventListener("mouseup",arguments.callee,!1)});Value.addListener(document,"mousemove",function(b){Dispatcher.notify(a.id,d(b))||this.removeEventListener("mousemove",arguments.callee,!1)});return{position:a,x:g,y:i,isClicked:b,isDown:j,clicks:l,isClickedOn:function(a){var a=Render.render(a),b=Elm.Signal.constant(!1);Value.addListener(a,"click",function(){Dispatcher.notify(b.id,!0);Dispatcher.notify(b.id,!1)});return Value.Tuple(Value.wrap(a),b)}}}();
-Elm.Random=function(){return{inRange:function(d){return function(a){return Elm.Signal.constant(Math.floor(Math.random()*(a-d+1))+d)}},randomize:function(d){return function(a){return function(g){return Elm.Signal.lift(function(){return Math.floor(Math.random()*(a-d+1))+d})(g)}}}}}();
-Elm.Time=function(){return{every:function(d){var d=1E3*d,a=Elm.Signal.constant(0),g=0;setInterval(function(){g+=d;Dispatcher.notify(a.id,g/1E3)},d);return a},after:function(d){var d=1E3*d,a=Elm.Signal.constant(!1);setTimeout(function(){Dispatcher.notify(a.id,!0)},d);return a},before:function(d){var d=1E3*d,a=Elm.Signal.constant(!0);setTimeout(function(){Dispatcher.notify(a.id,!1)},d);return a}}}();
-Elm.Window=function(){var d=Elm.Signal.constant(Value.Tuple(window.innerWidth,window.innerHeight));d.defaultNumberOfKids=2;var a=Elm.Signal.lift(function(a){return a[1]})(d);a.defaultNumberOfKids=0;var g=Elm.Signal.lift(function(a){return a[2]})(d);g.defaultNumberOfKids=0;Value.addListener(window,"resize",function(a){var g=document.getElementById("widthChecker").offsetWidth;Dispatcher.notify(d.id,Value.Tuple(g,window.innerHeight))||this.removeEventListener("resize",arguments.callee,!1)});return{dimensions:d,
-width:a,height:g}}();Value.addListener(document,"elm_log",function(d){console.log(d.value)});Value.addListener(document,"elm_title",function(d){document.title=d.value});Value.addListener(document,"elm_redirect",function(d){0<d.value.length&&(window.location=d.value)});Elm=Elm||{};
-Elm.Prelude=function(){var d=function(a){return function(g){var i=a%g,i=0==a?0:0<g?0<=a?i:i+g:-d(-a)(-g);return i==g?0:i}};return{eq:Value.eq,id:function(a){return a},not:function(a){return!a},fst:function(a){return a[1]},snd:function(a){return a[2]},rem:function(a){return function(d){return a%d}},div:function(a){return function(d){return~~(a/d)}},compare:function(a){return function(d){a="object"===typeof a?toText(a):a;d="object"===typeof d?toText(d):d;return[a===d?"EQ":a<d?"LT":"GT"]}},toFloat:function(a){return a},
-round:function(a){return Math.round(a)},floor:function(a){return Math.floor(a)},ceiling:function(a){return Math.ceil(a)},truncate:function(a){return~~a},readInt:function(a){var a=JavaScript.castStringToJSString(a),d=a.length;if(0===d)return Nothing;var i=0;if("-"==a[0]){if(1===d)return Nothing;i=1}for(;i<d;++i)if(!Char.isDigit(a[i]))return Nothing;return Just(parseInt(a))},readFloat:function(a){var a=JavaScript.castStringToJSString(a),d=a.length;if(0===d)return Nothing;var i=0;if("-"==a[0]){if(1===
-d)return Nothing;i=1}for(var j=0;i<d;++i)if(!Char.isDigit(a[i])){if("."===a[i]&&(j+=1,1>=j))continue;return Nothing}return Just(parseFloat(a))},sqrt:Math.sqrt,abs:Math.abs,pi:Math.PI,e:Math.E,sin:Math.sin,cos:Math.cos,tan:Math.tan,asin:Math.asin,acos:Math.acos,atan:Math.atan,atan2:function(a){return function(d){return Math.atan2(a,d)}},mod:d,min:function(a){return function(d){return Math.min(a,d)}},max:function(a){return function(d){return Math.max(a,d)}},flip:function(a){return function(d){return function(i){return a(i)(d)}}},
-clamp:function(a){return function(d){return function(i){return Math.min(d,Math.max(a,i))}}},curry:function(a){return function(d){return function(i){return a(["Tuple2",d,i])}}},uncurry:function(a){return function(d){if("Tuple2"!==d[0])throw"Function was uncurry'd but was not given a pair.";return a(d[1])(d[2])}},logBase:function(a){return function(d){return Math.log(d)/Math.log(a)}},Just:Elm.Maybe.Just,Nothing:Elm.Maybe.Nothing,maybe:Elm.Maybe.maybe,map:Elm.List.map,filter:Elm.List.filter,head:Elm.List.head,
-tail:Elm.List.tail,last:Elm.List.last,length:Elm.List.length,reverse:Elm.List.reverse,foldr:Elm.List.foldr,foldr1:Elm.List.foldr1,foldl:Elm.List.foldl,foldl1:Elm.List.foldl1,and:Elm.List.and,or:Elm.List.or,all:Elm.List.all,any:Elm.List.any,sum:Elm.List.sum,product:Elm.List.product,concat:Elm.List.concat,concatMap:Elm.List.concatMap,maximum:Elm.List.maximum,minimum:Elm.List.minimum,scanl:Elm.List.scanl,scanl1:Elm.List.scanl1,take:Elm.List.take,drop:Elm.List.drop,zip:Elm.List.zip,unzip:Elm.List.unzip,
-lift:Elm.Signal.lift,lift2:Elm.Signal.lift2,lift3:Elm.Signal.lift3,lift4:Elm.Signal.lift4,foldp:Elm.Signal.foldp,foldp1:Elm.Signal.foldp1,foldp_:Elm.Signal.foldp_,constant:Elm.Signal.constant,count:Elm.Signal.count,keepIf:Elm.Signal.keepIf,dropIf:Elm.Signal.dropIf,keepWhen:Elm.Signal.keepWhen,dropWhen:Elm.Signal.dropWhen,dropRepeats:Elm.Signal.dropRepeats,sampleOn:Elm.Signal.sampleOn}}();
-(function(){var d=function(a){for(var d in a)Elm.Prelude[d]=a[d]};d(Elm.Color);d(Elm.Text);d(Elm.Graphics);show=Value.show})();
-(function(){for(var d in Elm)this[d]=Elm[d];Elm.Automaton=function(){function a(a){return["Automaton",a]}function d(a){return["DragFrom",a]}function i(b){return function(c){var d;a:{switch(b[0]){case "Automaton":d=b[1];break a}throw"Non-exhaustive pattern match in case";}var e;a:{switch(c[0]){case "Automaton":e=c[1];break a}throw"Non-exhaustive pattern match in case";}return a(function(a){var a=d(a),b;a:{switch(a[0]){case "Tuple2":b=a[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(a[0]){case "Tuple2":a=
-a[2];break a}throw"Non-exhaustive pattern match in case";}var c=e(b);a:{switch(c[0]){case "Tuple2":b=c[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(c[0]){case "Tuple2":c=c[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",b,i(a)(c)]})}}function j(b){return a(function(a){var c=unzip(map(function(b){a:{switch(b[0]){case "Automaton":b=b[1](a);break a}throw"Non-exhaustive pattern match in case";}return b})(b)),d;a:{switch(c[0]){case "Tuple2":d=c[1];break a}throw"Non-exhaustive pattern match in case";
-}a:{switch(c[0]){case "Tuple2":c=c[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",d,j(c)]})}function b(c){return a(function(a){return["Tuple2",c(a),b(c)]})}function l(b){return function(c){return a(function(a){a=c(a)(b);return["Tuple2",a,l(a)(c)]})}}function h(b){return function(c){return a(function(a){var d=c(a)(b);a:{switch(d[0]){case "Tuple2":a=d[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(d[0]){case "Tuple2":d=d[2];break a}throw"Non-exhaustive pattern match in case";
-}return["Tuple2",a,h(d)(c)]})}}function f(a){return function(b){a:{switch(a[0]){case "Tuple2":b:{switch(b[0]){case "Tuple2":b=["Tuple2",a[1]-b[1],a[2]-b[2]];break b}break}break a}throw"Non-exhaustive pattern match in case";}return b}}function c(a){return function(b){var c;a:{switch(a[0]){case "Tuple2":b:{switch(b[0]){case "Tuple2":var e=function(a){return["Tuple2",b[2],["Tuple2",a,b[2]]]};c=function(){switch(b[1][0]){case "DragFrom":var c;a[1]?c=["Tuple2",uncurry(move)(f(a[2])(b[1][1]))(b[2]),["Tuple2",
-d(b[1][1]),b[2]]]:(c=uncurry(move)(f(a[2])(b[1][1]))(b[2]),c=["Tuple2",c,["Tuple2",m,c]]);return c;case "Ignore":return e(a[1]?s:m);case "Listen":return e(not(a[1])?m:isWithin(a[2])(b[2])?d(a[2]):s)}throw"Non-exhaustive pattern match in case";}();break b}break}break a}throw"Non-exhaustive pattern match in case";}return c}}var e=[],n;for(n in Elm.Prelude)0<=e.indexOf(n)||(this[n]=Elm.Prelude[n]);var m=["Listen"],s=["Ignore"],e=l(0)(function(){return function(a){return 1+a}});return{Automaton:a,run:function(a){return function(b){a:{switch(a[0]){case "Automaton":b=
-lift(fst)(foldp_(function(a){return function(b){a:{switch(b[0]){case "Tuple2":switch(b[2][0]){case "Automaton":b=b[2][1](a);break a}}throw"Non-exhaustive pattern match in case";}return b}})(a[1])(b));break a}throw"Non-exhaustive pattern match in case";}return b}},step:function(a){return function(b){a:{switch(a[0]){case "Automaton":b=a[1](b);break a}throw"Non-exhaustive pattern match in case";}return b}},composeAuto:i,combine:j,pure:b,init:l,init_:h,count:e,Listen:m,Ignore:s,DragFrom:d,vecSub:f,stepDrag:c,
-draggable:function(a){return h(["Tuple2",m,a])(c)}}}()})();
diff --git a/elm-runtime-0.6.js b/elm-runtime-0.6.js
new file mode 100644
--- /dev/null
+++ b/elm-runtime-0.6.js
@@ -0,0 +1,134 @@
+Elm={};var Guid=function(){var d=0;return{guid:function(){return d+=1}}}();
+Elm.JavaScript=function(){function d(b){for(var a=["Nil"],c=b.length;c--;)a=["Cons",b[c],a];return a}function c(b){for(var a=[];"Cons"===b[0];)a.push(b[1]),b=b[2];return a}function b(b){return b.slice(1)}function e(b){return["Tuple"+b.length].concat(b)}return{castJSBoolToBool:function(b){return b},castBoolToJSBool:function(b){return b},castJSNumberToFloat:function(b){return b},castFloatToJSNumber:function(b){return b},castJSNumberToInt:function(b){return~~b},castIntToJSNumber:function(b){return b},
+Experimental:{castJSElementToElement:function(b){return function(a){return function(c){return["Element",Guid.guid(),["EExternalHtml",c],b,a,1,Nothing,Nothing]}}},castElementToJSElement:function(b){return Render.render(b)}},castJSArrayToList:d,castListToJSArray:c,castJSStringToString:d,castStringToJSString:function(b){return"string"===typeof b?b:c(b).join("")},castTupleToJSTuple2:b,castTupleToJSTuple3:b,castTupleToJSTuple4:b,castTupleToJSTuple5:b,castJSTupleToTuple2:e,castJSTupleToTuple3:e,castJSTupleToTuple4:e,
+castJSTupleToTuple5:e}}();var JSjson=window.JSON;
+Elm.JSON=function(){function d(a,b){return function(c){return function(n){var h=e.castStringToJSString(c);return n[1].hasOwnProperty(h)&&(n=n[1][h],n[0]===a)?n[1]:b}}}function c(a){return function(b){function c(a){switch(a[0]){case "JsonNull":return null;case "JsonString":return e.castStringToJSString(a[1]);case "JsonObject":var h={},a=a[1][1],f;for(f in a)h[f]=c(a[f]);return h;case "JsonArray":h=e.castListToJSArray(a[1]);for(f=h.length;f--;)h[f]=c(h[f]);return h;default:return a[1]}}return JSjson.stringify(c(["JsonObject",
+b]),null,e.castStringToJSString(a))}}function b(a){function b(a){switch(typeof a){case "string":return["JsonString",e.castJSStringToString(a)];case "number":return["JsonNumber",e.castJSNumberToFloat(a)];case "boolean":return["JsonBool",e.castJSBoolToBool(a)];case "object":if(null===a)return["JsonNull"];for(var h in a)a[h]=b(a[h]);return a instanceof Array?["JsonArray",e.castJSArrayToList(a)]:["JsonObject",["JSON",a]]}}var a=JSjson.parse(a),c;for(c in a)a[c]=b(a[c]);return["JSON",a]}var e=Elm.JavaScript,
+i=["JSON",{}];return{empty:i,singleton:function(a){return function(b){var c={};c[e.castStringToJSString(a)]=b;return["JSON",c]}},insert:function(a){return function(b){return function(c){var c=c[1],n={},h;for(h in c)n[h]=c[h];n[e.castStringToJSString(a)]=b;return["JSON",n]}}},lookup:function(a){return function(b){var c=e.castStringToJSString(a);return b[1].hasOwnProperty(c)?["Just",b[1][c]]:["Nothing"]}},findString:d("JsonString",["Nil"]),findObject:d("JsonObject",i),findArray:d("JsonArray",["Nil"]),
+findWithDefault:function(a){return function(b){return function(c){var n=e.castStringToJSString(b);return c[1].hasOwnProperty(n)?c[1][n]:a}}},remove:function(a){return function(b){var b=b[1],c={},n;for(n in b)c[n]=b[n];delete c[e.castStringToJSString(a)];return["JSON",c]}},toPrettyJSString:c,toJSString:c(""),fromJSString:b,toPrettyString:function(a){return function(b){return e.castJSStringToString(c(a)(b))}},toString:function(a){return e.castJSStringToString(c("")(a))},fromString:function(a){return b(e.castStringToJSString(a))},
+toList:function(a){var a=a[1],b=[],c;for(c in a)b.push(Value.Tuple(e.castJSStringToString(c),a[c]));return e.castJSArrayToList(b)},fromList:function(a){for(var a=e.castListToJSArray(a),b={},c=a.length;c--;)b[e.castStringToJSString(a[c][1])]=a[c][2];return["JSON",b]},JsonString:function(a){return["JsonString",a]},JsonNumber:function(a){return["JsonNumber",a]},JsonBool:function(a){return["JsonBool",a]},JsonNull:["JsonNull"],JsonArray:function(a){return["JsonArray",a]},JsonObject:function(a){return["JsonObject",
+a]}}}();
+var Value=function(){function d(a){if(0==a.length)return a;for(var a=a.replace(/"/g,"&#34;").replace(/'/g,"&#39;").replace(/</g,"&#60;").replace(/>/g,"&#62;").replace(/\n/g,"<br/>"),a=a.split("<br/>"),b=a.length;b--;){var c=a,n=b,h;h=a[b];if(0!=h.length){h=h.split("");" "==h[0]&&(h[0]="&nbsp;");for(var f=h.length;--f;)" "==h[f][0]&&" "==h[f-1]&&(h[f-1]+=h[f],h[f]="");for(f=h.length;f--;)if(1<h[f].length&&" "==h[f][0]){for(var g=h[f].split(""),e=g.length-2;0<=e;e-=2)g[e]="&nbsp;";h[f]=g.join("")}h=h.join("");
+h=" "===h[h.length-1]?h.slice(0,-1)+"&nbsp;":h}c[n]=h}return a.join("<br/>")}var c=function(a,b){if("object"===typeof a){if(a===b)return!0;if(a.length!==b.length)return!1;for(var e=a.length;e--;)if(!c(a[e],b[e]))return!1;return!0}return a===b},b=function(a){if("boolean"===typeof a)return a?"True":"False";if("number"!==typeof a){if("string"===typeof a&&2>a.length)return"'"+a+"'";if(a[0]){if("Tuple"===a[0].substring(0,5)){for(var c="",e=a.length;--e;)c=","+b(a[e])+c;","===c[0]&&(c=c.substring(1));return"("+
+c+")"}if("Cons"===a[0])for(var e="string"===typeof a[1]?'"':"]",n="string"===typeof a[1]?"":",",h="string"===typeof a[1]?function(a){return a}:b,c=("string"===typeof a[1]?'"':"[")+h(a[1]),a=a[2];;)if("Cons"===a[0])c+=n+h(a[1]),a=a[2];else return c+e;else{if("Nil"===a[0])return"[]";if("JSON"===a[0])return"(JSON.fromList "+b(Elm.JSON.toList(a))+")";if("RBNode"===a[0]||"RBEmpty"===a[0])return a=Elm.Dict.foldr(function(a){return function(h){return function(b){return["Cons",["Tuple2",a,h],b]}}})(["Nil"])(a),
+c="Dict","Cons"===a[0]&&"Tuple0"===a[1][2][0]&&(c="Set",a=Elm.List.map(function(a){return a[1]})(a)),"("+c+".fromList "+b(a)+")";c="";for(e=a.length;--e;)c=" "+b(a[e])+c;c=a[0]+c;return 1<a.length?"("+c+")":c}}}return a+""},e=function(a){for(var b=["Nil"],c=a.length;c--;)b=["Cons",a[c],b];return b},i;i=document.addEventListener?function(a,b,c){a.addEventListener(b,c,!1)}:function(a,b,c){a.attachEvent("on"+b,c)};return{eq:c,str:e,show:function(a){return e(b(a))},Tuple:function(){var a=arguments.length,
+b=Array(a+1);for(b[0]="Tuple"+arguments.length;a--;)b[a+1]=arguments[a];return b},append:function(a,b){if("string"===typeof a&&"string"===typeof b)return a.concat(b);if("Nil"===a[0])return b;for(var c=["Cons",a[1],["Nil"]],e=c,a=a[2];"Cons"===a[0];)e[2]=["Cons",a[1],["Nil"]],a=a[2],e=e[2];e[2]=b;return c},listToArray:function(a){for(var b=[];"Cons"===a[0];)b.push(a[1]),a=a[2];return b},toText:function(a){if("string"===typeof a)return d(a);for(var b=[];"Cons"===a[0];)b.push(a[1]),a=a[2];return d(b.join(""))},
+properEscape:d,getTextSize:function(a,b,c){var e=document.createElement("div");e.innerHTML=c;e.style.textAlign="left";0<a&&(e.style.width=a+"px");e.style.visibility="hidden";e.style.styleFloat="left";e.style.cssFloat="left";document.body.appendChild(e);c=window.getComputedStyle(e,null);a=c.getPropertyValue("width").slice(0,-2)-0;c=c.getPropertyValue("height").slice(0,-2)-0;document.body.removeChild(e);return[Math.ceil(a),Math.ceil(Math.max(b,c))]},getSize:function(a){a=a.cloneNode(!0);a.style.visibility=
+"hidden";a.style.styleFloat="left";a.style.cssFloat="left";document.body.appendChild(a);var b=a.offsetWidth,c=a.offsetHeight;document.body.removeChild(a);return[b,c]},getExcess:function(a){a=a.cloneNode(!0);a.style.visibility="hidden";a.style.styleFloat="left";a.style.cssFloat="left";document.body.appendChild(a);var b=a.offsetWidth,c=a.offsetHeight,e=window.getComputedStyle(a,null),h=e.getPropertyValue("width").slice(0,-2)-0,e=e.getPropertyValue("height").slice(0,-2)-0;document.body.removeChild(a);
+return[b-h,c-e]},groupForms:function(a){for(var a=Elm.JavaScript.castListToJSArray(a),b=[],c=[],e=a.length;e--;){var h=a[e];switch(h[4][0]){case "FElement":0<c.length&&(b.push(c),c=[]);b.push(h);break;default:c.push(h)}}0<c.length&&b.push(c);return b},wrap:function(a){var b=Value.getSize(a);return["Element",Guid.guid(),["EHtml",a],b[0],b[1],1,["Nothing"],["Nothing"]]},addListener:i}}();
+Elm.List=function(){function d(b){return function(a){if("Nil"===a[0])return a;"Cons"!==a[0]&&h("map");for(var c=["Cons",b(a[1]),["Nil"]],f=c,a=a[2];"Cons"===a[0];)f[2]=["Cons",b(a[1]),["Nil"]],a=a[2],f=f[2];return c}}function c(a){return function(b){return function(c){var f=b;if("Nil"===c[0])return f;for("Cons"!==c[0]&&h("foldl");"Cons"===c[0];)f=a(c[1])(f),c=c[2];return f}}}function b(a){return function(b){return function(c){var f=b;if("Nil"===c[0])return f;"Cons"!==c[0]&&h("foldr");for(var g=[];"Cons"===
+c[0];)g.push(c[1]),c=c[2];for(c=g.length;c--;)f=a(g[c])(f);return f}}}function e(a){return function(b){var h;"Cons"!==b[0]?h=void 0:(h=b[1],b=b[2],h=c(a)(h)(b));return h}}function i(a){return function(b){return function(c){if("Nil"===c[0])return["Cons",b,["Nil"]];"Cons"!==c[0]&&h("scanl");for(var f=[b];"Cons"===c[0];)b=a(c[1])(b),f.push(b),c=c[2];for(var c=["Nil"],g=f.length;g--;)c=["Cons",f[g],c];return c}}}function a(b){return function(c){a:{for(var h=[function(b){return"Nil"!==b[0]?void 0:["Tuple2",
+["Nil"],["Nil"]]},function(c){if("Cons"===c[0]){var h=c[1],c=c[2];var f=a(b)(c);"Tuple2"!==f[0]?h=void 0:(c=f[1],f=f[2],h=b(h)?["Tuple2",["Cons",h,c],f]:["Tuple2",c,["Cons",h,f]]);return h}}],f=h.length;f--;){var g=h[f](c);if(void 0!==g){c=g;break a}}c=void 0}return c}}function j(b){a:{for(var a=[function(b){return"Nil"!==b[0]?void 0:["Tuple2",["Nil"],["Nil"]]},function(b){if("Cons"!==b[0])b=void 0;else if(b=["Tuple2",b[1],j(b[2])],"Tuple2"!==b[0]||"Tuple2"!==b[1][0])b=void 0;else var a=b[1][1],c=
+b[1][2],b="Tuple2"!==b[2][0]?void 0:["Tuple2",["Cons",a,b[2][1]],["Cons",c,b[2][2]]];return b}],c=a.length;c--;){var h=a[c](b);if(void 0!==h){b=h;break a}}b=void 0}return b}function l(b){return function(a){a:{for(var c=[function(b){return"Nil"!==b[0]?void 0:["Nil"]},function(b){if("Cons"===b[0]){var a=b[1];return"Nil"!==b[2][0]?void 0:["Cons",a,["Nil"]]}},function(a){if("Cons"===a[0]){var c=a[1];if("Cons"===a[2][0]){var h=a[2][1],a=a[2][2];return["Cons",c,["Cons",b,l(b)(["Cons",h,a])]]}}}],h=c.length;h--;){var f=
+c[h](a);if(void 0!==f){a=f;break a}}a=void 0}return a}}function n(b){return function(a){a:{for(var c=[function(b){return"Nil"!==b[0]?void 0:["Nil"]},function(b){if("Cons"===b[0]){var a=b[1];return"Nil"!==b[2][0]?void 0:a}},function(a){if("Cons"===a[0]){var c=a[1];if("Cons"===a[2][0]){var h=a[2][1],a=a[2][2];return Value.append(c,Value.append(b,n(b)(["Cons",h,a])))}}}],h=c.length;h--;){var f=c[h](a);if(void 0!==f){a=f;break a}}a=void 0}return a}}var h=function(b){throw"Function '"+b+"' expecting a list!";
+},f=c(function(b){return function(a){return["Cons",b,a]}})(["Nil"]),g=b(function(b){return function(a){return Value.append(b,a)}})(["Nil"]),s=c(function(b){return function(a){return b&&a}})(!0),k=c(function(b){return function(a){return b||a}})(!1),p=c(function(b){return function(a){return b+a}})(0),m=c(function(b){return function(a){return b*a}})(1),x=e(function(b){return function(a){return Math.max(b,a)}}),u=e(function(b){return function(a){return Math.min(b,a)}});return{head:function(b){if("Cons"!==
+b[0])throw"Error: 'head' only accepts lists of length greater than one.";return b[1]},tail:function(b){if("Cons"!==b[0])throw"Error: 'tail' only accepts lists of length greater than one.";return b[2]},last:function(b){if("Cons"!==b[0])throw"Error: 'last' only accepts lists of length greater than one.";for(var a=b[1];"Cons"===b[0];)a=b[1],b=b[2];return a},map:d,foldl:c,foldr:b,foldl1:e,foldr1:function(b){return function(a){if("Nil"===a[0])throw"'foldr1' requires an non-empty list.";"Cons"!==a[0]&&
+h("foldr1");for(var c=[];"Cons"===a[0];)c.push(a[1]),a=a[2];for(var a=c.pop(),f=c.length;f--;)a=b(c[f])(a);return a}},scanl:i,scanl1:function(b){return function(a){if("Cons"!==a[0])throw"Error: 'scanl1' requires a list of at least length 1.";return i(b)(a[1])(a[2])}},filter:function(b){return function(a){if("Nil"===a[0])return a;"Cons"!==a[0]&&h("filter");for(var c=[];"Cons"===a[0];)b(a[1])&&c.push(a[1]),a=a[2];for(var a=["Nil"],f=c.length;f--;)a=["Cons",c[f],a];return a}},length:function(b){for(var a=
+0;"Cons"===b[0];)a+=1,b=b[2];return a},reverse:f,concat:g,concatMap:function(b){return function(a){return g(d(b)(a))}},and:s,or:k,all:function(b){return c(function(a){return function(c){return c&&b(a)}})(!0)},any:function(b){return c(function(a){return function(c){return c||b(a)}})(!1)},sum:p,product:m,maximum:x,minimum:u,partition:a,zipWith:function(b){return function(a){return function(c){if("Nil"===a[0]||"Nil"===c[0])return["Nil"];("Cons"!==a[0]||"Cons"!==c[0])&&h("zipWith");for(var f=[];"Cons"===
+a[0]&&"Cons"===c[0];)f.push(b(a[1])(c[1])),a=a[2],c=c[2];for(var c=["Nil"],g=f.length;g--;)c=["Cons",f[g],c];return c}}},zip:function(a){return function(b){if("Nil"===a[0]||"Nil"===b[0])return["Nil"];("Cons"!==a[0]||"Cons"!==b[0])&&h("zip");for(var c=[];"Cons"===a[0]&&"Cons"===b[0];)c.push(["Tuple2",a[1],b[1]]),a=a[2],b=b[2];for(var b=["Nil"],f=c.length;f--;)b=["Cons",c[f],b];return b}},unzip:j,intersperse:l,intercalate:n,sort:function(b){if("Nil"===b[0])return b;"Cons"!==b[0]&&h("sort");for(var a=
+[];"Cons"===b[0];)a.push(b[1]),b=b[2];a.sort(function(b,a){return b-a});for(var b=["Nil"],c=a.length;c--;)b=["Cons",a[c],b];return b},take:function(b){return function(a){if(0>=b)return["Nil"];if("Nil"===a[0])return a;"Cons"!==a[0]&&h("take");var c=["Cons",a[1],["Nil"]],f=c,a=a[2];for(--b;"Cons"===a[0]&&0<b;)f[2]=["Cons",a[1],["Nil"]],f=f[2],a=a[2],--b;return c}},drop:function(b){return function(a){if("Nil"===a[0])return a;for("Cons"!==a[0]&&h("drop");"Cons"===a[0]&&0<b;)a=a[2],--b;return a}}}}();
+Elm.Maybe=function(){function d(b){return function(c){return"Just"===b[0]?["Cons",b[1],c]:c}}function c(b){return function(c){return function(d){var a=b(c);return"Just"===a[0]?["Cons",a[1],d]:d}}}return{Just:function(b){return["Just",b]},Nothing:["Nothing"],catMaybes:Elm.List.foldr(d)(["Nil"]),isJust:function(b){return"Just"===b[0]},isNothing:function(b){return"Nothing"===b[0]},fromMaybe:function(b){return function(c){return"Just"===c[0]?c[1]:b}},consMaybe:d,mapMaybe:function(b){return Elm.List.foldr(c(b))(["Nil"])},
+maybe:function(b){return function(c){return function(d){return"Just"===d[0]?c(d[1]):b}}}}}();
+Elm.Char=function(){function d(b,a){return function(c){c=c.charCodeAt(0);return b<=c&&c<=a}}var c=d(48,57),b=d(97,102),e=d(65,70);return{fromCode:function(b){return String.fromCharCode(b)},toCode:function(b){return b.charCodeAt(0)},toUpper:function(b){return b.toUpperCase()},toLower:function(b){return b.toLowerCase()},toLocaleUpper:function(b){return b.toLocaleUpperCase()},toLocaleLower:function(b){return b.toLocaleLowerCase()},isLower:d(97,122),isUpper:d(65,90),isDigit:c,isOctDigit:d(48,55),isHexDigit:function(d){return c(d)||
+b(d)||e(d)}}}();
+Elm.Color=function(){function d(c){var b=c.value*c.saturation,e=c.hue/60,d=b*(1-Math.abs(e%2-1)),a=0,j=0,l=0;0<=e&&1>e?(a=b,j=d,l=0):1<=e&&2>e?(a=d,j=b,l=0):2<=e&&3>e?(a=0,j=b,l=d):3<=e&&4>e?(a=0,j=d,l=b):4<=e&&5>e?(a=d,j=0,l=b):5<=e&&6>e&&(a=b,j=0,l=d);c=c.value-b;return["Color",Math.round(255*(a+c)),Math.round(255*(j+c)),Math.round(255*(l+c)),1]}return{rgba:function(c){return function(b){return function(e){return function(d){return["Color",c,b,e,d]}}}},rgb:function(c){return function(b){return function(e){return["Color",c,
+b,e,1]}}},hsva:function(c){return function(b){return function(e){return function(i){var a=d({hue:c,saturation:b,value:e});a[4]=i;return a}}}},hsv:function(c){return function(b){return function(e){return d({hue:c,saturation:b,value:e})}}},red:["Color",255,0,0,1],green:["Color",0,255,0,1],blue:["Color",0,0,255,1],yellow:["Color",255,255,0,1],cyan:["Color",0,255,255,1],magenta:["Color",255,0,255,1],black:["Color",0,0,0,1],white:["Color",255,255,255,1],gray:["Color",128,128,128,1],grey:["Color",128,128,
+128,1],complement:function(c){var b;b=c[1]/255;var e=c[2]/255,c=c[3]/255,i=Math.max(b,e,c),a=Math.min(b,e,c),a=i-a,j=0;0===a?j=0:i===b?j=(e-c)/a%6:i===e?j=(c-b)/a+2:i===c&&(j=(b-e)/a+4);b={value:i,hue:60*j,saturation:0===i?0:a/i};b.hue=(b.hue+180)%360;return d(b)},extract:function(c){return 1===c[4]?"rgb("+c[1]+","+c[2]+","+c[3]+")":"rgba("+c[1]+","+c[2]+","+c[3]+","+c[4]+")"}}}();
+var Collage=function(){function d(b,a){var c=a.length-1;if(!(0>=c))for(b.moveTo(a[c][1],a[c][2]);c--;)b.lineTo(a[c][1],a[c][2])}function c(b,a,c,g){0===b.length&&(b=[8,4]);var e=g.length-1;if(!(0>=e)){var k=g[e][1],d=g[e][2],m=0,l=0,i=0,j=0,q=0,r=0,v=b.length,w=!0,y=b[0];for(a.moveTo(k,d);e--;){m=g[e][1];l=g[e][2];i=m-k;j=l-d;for(q=Math.sqrt(i*i+j*j);y<=q;)k+=i*y/q,d+=j*y/q,a[w?"lineTo":"moveTo"](k,d),i=m-k,j=l-d,q=Math.sqrt(i*i+j*j),w=!w,r=(r+1)%v,y=b[r];0<q&&(a[w?"lineTo":"moveTo"](m,l),y-=q);k=
+m;d=l}}a.strokeStyle=Elm.Color.extract(c);a.stroke()}function b(b,a,f,g,e){a.clearRect(0,0,f,g);for(f=e.length;f--;){var k=e[f],p=b,g=a,m=k[1],i=k[2],j=k[3][1],t=k[3][2],k=k[4];g.save();(0!==j||0!==t)&&g.translate(j,t);m!==~~m&&g.rotate(2*Math.PI*m);1!==i&&g.scale(i,i);g.beginPath();switch(k[0]){case "FLine":a:switch(p=g,m=k,k=m[3][1],m[1][0]){case "Solid":m=m[2];d(p,k);p.strokeStyle=Elm.Color.extract(m);p.stroke();break;case "Dotted":c([3,3],p,m[2],k);break a;case "Dashed":c([8,4],p,m[2],k);break a;
+case "Custom":c(m[1][1],p,m[2],k)}break;case "FShape":a:switch(j=p,i=g,p=k[1],m=k[2],k=k[3][1],p[0]){case "Filled":p=i;d(p,k);p.fillStyle=Elm.Color.extract(m);p.fill();break a;case "Outlined":p=i;d(p,k);p.strokeStyle=Elm.Color.extract(m);p.stroke();break a;case "Textured":m=j;p=p[1];j=new Image;j.src=l.castStringToJSString(p);j.onload=m;d(i,k);i.fillStyle=i.createPattern(j,"repeat");i.fill();break a;case "CustomOutline":c(p[1],i,m,k)}break;case "FImage":m=g,i=k[1],j=k[2],k=k[3],t=new Image,t.onload=
+p,t.src=l.castStringToJSString(k),m.drawImage(t,-i/2,-j/2,i,j)}g.restore()}}function e(a,c,f){var g=Render.newElement("canvas"),a=~~a,c=~~c;g.style.width=a+"px";g.style.height=c+"px";g.style.display="block";g.width=a;g.height=c;if(g.getContext){var e=g.getContext("2d");b(function(){b(this,e,a,c,f)},e,a,c,f);return g}g.innerHTML="Your browser does not support the canvas element.";return g}function i(a,b,c,g,e,k,d){var m=Render.render(d),c="translate("+(e-d[3]/2)+"px,"+(k-d[4]/2)+"px) "+(1===g?"":"scale("+
+g+","+g+")")+" "+(c===~~c?"":"rotate("+360*c+"deg)");m.style.transform=c;m.style.msTransform=c;m.style.MozTransform=c;m.style.webkitTransform=c;m.style.OTransform=c;c=Render.newElement("div");Render.addTo(c,m);c.style.width=~~a+"px";c.style.height=~~b+"px";c.style.overflow="hidden";return c}function a(a,c,f){if(!Value.eq(f,c)){var g=a.style.width.slice(0,-2)-0,d=a.style.height.slice(0,-2)-0;if("object"===typeof f[0]){if("object"===typeof c[0]&&a.getContext){var k=a.getContext("2d");return b(function(){b(this,
+k,g,d,f)},k,g,d,f)}c=e(g,d,f);c.style.position="absolute";return a.parentNode.replaceChild(c,a)}c=i(g,d,f[1],f[2],f[3][1],f[3][2],f[4][1]);c.style.position="absolute";return a.parentNode.replaceChild(c,a)}}function j(a,b,c,g,e){var k=0,d,m=(a[1]-g[1])/c,a=(a[2]-g[2])/c;0!==b&&(b*=-2*Math.PI,c=m*Math.cos(b)-a*Math.sin(b),a=m*Math.sin(b)+a*Math.cos(b),m=c);if(0===e.length)return!1;d=e[0];for(c=e.length-1;c--;){b=e[c];g=d[1];d=d[2];var i=b[1],l=b[2];if(d<l)var j=d,q=l;else j=l,q=d;if(g<i)var r=g,v=i;
+else r=i,v=g;j<a&&a<=q&&m<=v&&(m<=r||m<=(a-d)*(i-g)/(l-d)+g)&&++k;d=b}return 1===k%2}var l=Elm.JavaScript;return{collage:function(a,b,c){if(0===c.length)return e(a,b,[]);for(var g=Array(c.length),d=c.length;d--;){var k=c[d];g[d]="string"===typeof k[0]?i(a,b,k[1],k[2],k[3][1],k[3][2],k[4][1]):e(a,b,k)}return 1===c.length?g[0]:Render.flowWith(Render.goIn,function(a){return a},g)},updateCollage:function(b,c,f){if(1===f.length)return a(b,c[0],f[0]);for(var b=b.childNodes,g=b.length,e=g;e--;)a(b[g-e-1],
+c[e],f[e])},insideForm:function(a){return function(b){var c=a[1],g=a[2];if(6>b.length){var e=b[3][1],d=b[3][2],p=0,i=b[2];switch(b[4][0]){case "FShape":for(var l=b[4][3][1],u=l.length;--u;)var t=l[u],p=Math.max(p,t[1]*t[1]+t[2]*t[2]);p*=i*i;break;case "FImage":l=i*b[4][1]/2;i=i*b[4][2]/2;p=l*l+i*i;break;case "FElement":l=i*b[4][1][3]/2,i=i*b[4][1][4]/2,p=l*l+i*i}b.push(function(b,a){var c=b-e,f=a-d;return c*c+f*f<p+1})}if(!b[5](c,g))return!1;var q,r;switch(b[4][0]){case "FShape":return j(a,b[1],b[2],
+b[3],b[4][3][1]);case "FLine":return!1;case "FImage":q=b[4][1]/2;r=b[4][2]/2;break;case "FElement":q=b[4][1][3]/2,r=b[4][1][4]/2}return j(a,b[1],b[2],b[3],[[null,q,r],[null,-q,r],[null,-q,-r],[null,q,-r],[null,q,r]])}}}}();
+Elm.Graphics=function(){function d(b){return function(a){return["Position",b,a]}}function c(b){return function(a){return["EText",b,a]}}function b(b){return function(a){return["EFlow",b,m.castListToJSArray(a)]}}function e(b){return["Line",m.castListToJSArray(b)]}function i(b){return function(a){var c=m.castListToJSArray(b);0<c.length&&c.push(c[0]);return["Shape",c,a]}}function a(b){return function(a){return function(c){return function(f){return["Form",b,a,c,f]}}}}function j(b){return function(a){return function(c){return["FLine",
+b,a,c]}}}function l(b){return function(a){return function(c){return["FShape",b,a,c]}}}function n(b,a,c,f,h,g){return["Element",Guid.guid(),b,a,c,f,h,g]}function h(b,a,c){return["Element",Guid.guid(),b,a,c,1,["Nothing"],["Nothing"]]}function f(b){return~~b[3]}function g(b){return~~b[4]}function s(b){return function(a){return function(c){return h(["EImage",m.castStringToJSString(c)],b,a)}}}function k(b){return function(a){return h(w,b,a)}}function p(b){return function(a){return function(c){var f=map(function(c){return["Tuple2",
+b/2*Math.cos(2*(Math.PI/50)*c),a/2*Math.sin(2*(Math.PI/50)*c)]}),h=49,g=["Nil"];if(0<=h){do g=["Cons",h,g];while(0<h--)}return i(f(g))(c)}}}for(this.i in Elm.List)eval("var "+this.i+" = Elm.List[this.i];");var m=Elm.JavaScript,x=["DRight"],u=["DDown"],t=["DOut"],q=["Near"],r=["Mid"],v=["Far"],w=["EEmpty"],y=["Solid"],z=["Dotted"],A=["Dashed"],B=["Filled"],C=["Outlined"],D=d(q)(q),E=d(v)(q),F=d(q)(v),G=d(v)(v),H=d(q)(r),I=d(v)(r),q=d(r)(q),v=d(r)(v),r=d(r)(r);return{left:["DLeft"],right:x,down:u,up:["DUp"],
+inward:["DIn"],outward:t,topLeft:D,topRight:E,bottomLeft:F,bottomRight:G,midLeft:H,midRight:I,midTop:q,midBottom:v,middle:r,middleAt:function(b){return function(a){return["PositionAt",b,a]}},topLeftAt:function(b){return function(a){return["PositionTL",b,a]}},topRightAt:function(b){return function(a){return["PositionTR",b,a]}},bottomLeftAt:function(b){return function(a){return["PositionBL",b,a]}},bottomRightAt:function(b){return function(a){return["PositionBR",b,a]}},absolute:function(b){return["Absolute",
+b]},relative:function(b){return["Relative",b]},width:function(b){return function(a){var c=a[2];switch(c[0]){case "EImage":case "EVideo":return n(a[2],b,a[4]*b/a[3],a[5],a[6],a[7]);case "EText":return c=Value.getTextSize(b,a[4],c[2]),n(a[2],b,c[1],a[5],a[6],a[7])}return n(a[2],b,a[4],a[5],a[6],a[7])}},height:function(b){return function(a){switch(a[2][0]){case "EImage":case "EVideo":return n(a[2],a[3]*b/a[4],b,a[5],a[6],a[7])}return n(a[2],a[3],b,a[5],a[6],a[7])}},size:function(b){return function(a){return function(c){return n(c[2],
+b,a,c[5],c[6],c[7])}}},opacity:function(b){return function(a){return n(a[2],a[3],a[4],b,a[6],a[7])}},color:function(b){return function(a){return n(a[2],a[3],a[4],a[5],["Just",b],a[7])}},link:function(a){return function(b){return n(b[2],b[3],b[4],b[5],b[6],["Just",m.castStringToJSString(a)])}},widthOf:f,heightOf:g,sizeOf:function(b){return["Tuple2",~~b[3],~~b[4]]},text:function(b){var a=Value.getTextSize(0,0,b);return h(c("left")(b),a[0],a[1])},asText:function(b){var b=Elm.Text.monospace(Value.toText(Value.show(b))),
+a=Value.getTextSize(0,0,b);return h(c("left")(b),a[0],a[1])},plainText:function(b){var b=Value.toText(b),a=Value.getTextSize(0,0,b);return h(c("left")(b),a[0],a[1])},centeredText:function(b){var a=Value.getTextSize(0,0,b);return h(c("center")(b),a[0],a[1])},justifiedText:function(b){var a=Value.getTextSize(0,0,b);return h(c("justify")(b),a[0],a[1])},rightedText:function(b){var a=Value.getTextSize(0,0,b);return h(c("right")(b),a[0],a[1])},image:s,images:function(b){var a=Elm.Signal.constant(k(0)(0)),
+b=Elm.Signal.lift(function(b){var b=m.castStringToJSString(b),c=new Image;c.onload=function(){Dispatcher.notify(a.id,s(this.width)(this.height)(b))};c.src=b})(b);return Elm.Signal.lift2(function(b){return function(){return b}})(a)(b)},video:function(b){return function(a){return function(c){return h(["EVideo",m.castStringToJSString(c)],b,a)}}},fittedImage:function(b){return function(a){return function(c){return h(["EFittedImage",m.castStringToJSString(c)],b,a)}}},flow:function(a){return function(c){var e;
+e=map(f)(c);a:{switch(a[0]){case "DLeft":e=sum(e);break a;case "DRight":e=sum(e);break a}e=maximum(e)}var d;d=map(g)(c);a:{switch(a[0]){case "DDown":d=sum(d);break a;case "DUp":d=sum(d);break a}d=maximum(d)}return h(b(a)(c),e,d)}},above:function(a){return function(c){return h(b(u)(["Cons",a,["Cons",c,["Nil"]]]),Math.max(~~a[3],~~c[3]),~~a[4]+~~c[4])}},below:function(a){return function(c){return h(b(u)(["Cons",c,["Cons",a,["Nil"]]]),Math.max(~~a[3],~~c[3]),~~a[4]+~~c[4])}},beside:function(a){return function(c){return h(b(x)(["Cons",
+a,["Cons",c,["Nil"]]]),~~a[3]+~~c[3],Math.max(~~a[4],~~c[4]))}},layers:function(a){return h(b(t)(a),maximum(map(f)(a)),maximum(map(g)(a)))},collage:function(a){return function(b){return function(c){return h(["ECollage",a,b,Value.groupForms(c)],a,b)}}},spacer:k,container:function(a){return function(b){return function(c){return function(f){return h(["EContainer",c,f],a,b)}}}},line:e,segment:function(a){return function(b){return e(["Cons",a,["Cons",b,["Nil"]]])}},polygon:i,rect:function(a){return function(b){return function(c){return i(["Cons",
+["Tuple2",0-a/2,0-b/2],["Cons",["Tuple2",0-a/2,b/2],["Cons",["Tuple2",a/2,b/2],["Cons",["Tuple2",a/2,0-b/2],["Nil"]]]]])(c)}}},oval:p,circle:function(a){return p(2*a)(2*a)},ngon:function(a){return function(b){return function(c){var f=map(function(c){return["Tuple2",b*Math.cos(2*(Math.PI/a)*c),b*Math.sin(2*(Math.PI/a)*c)]}),h=a-1,g=["Nil"];if(0<=h){do g=["Cons",h,g];while(0<h--)}return i(f(g))(c)}}},solid:function(b){return function(c){return a(0)(1)(["Tuple2",0,0])(j(y)(b)(c))}},dotted:function(b){return function(c){return a(0)(1)(["Tuple2",
+0,0])(j(z)(b)(c))}},dashed:function(b){return function(c){return a(0)(1)(["Tuple2",0,0])(j(A)(b)(c))}},customLine:function(b){return function(c){return function(f){return a(0)(1)(["Tuple2",0,0])(j(["Custom",m.castListToJSArray(b)])(c)(f))}}},filled:function(b){return function(c){return a(0)(1)(c[2])(l(B)(b)(c))}},outlined:function(b){return function(c){return a(0)(1)(c[2])(l(C)(b)(c))}},customOutline:function(b){return function(c){return function(f){return a(0)(1)(f[2])(l(["CustomOutline",m.castListToJSArray(b)])(c)(f))}}},
+textured:function(b){return function(c){return a(0)(1)(c[2])(l(["Textured",b])(null)(c))}},sprite:function(b){return function(c){return function(f){return function(h){return a(0)(1)(h)(["FImage",c,f,m.castStringToJSString(b)])}}}},toForm:function(b){return function(c){return a(0)(1)(b)(["FElement",c])}},rotate:function(b){return function(c){a:{switch(c[0]){case "Form":var f=c[2],h=c[3],g=c[4],c=a(b+c[1])(f)(h)(g);break a}throw"Non-exhaustive pattern match in case";}return c}},scale:function(b){return function(c){return a(c[1])(b*
+c[2])(c[3])(c[4])}},move:function(b){return function(c){return function(f){var h;a:{switch(f[0]){case "Form":h=f[1];var g=f[2],e=f[3],f=f[4];switch(e[0]){case "Tuple2":var d=e[1],e=e[2];h=a(h)(g)(["Tuple2",b+d,c+e])(f);break a}}throw"Non-exhaustive pattern match in case";}return h}}},isWithin:Collage.insideForm}}();
+Elm.Text=function(){function d(b){return Value.toText(b)}var c=function(b){return function(a){return"<"+b+' style="padding:0;margin:0">'+a+"</"+b+">"}},b=function(b,a){return function(c){return"<span style='"+b+":"+a+"'>"+c+"</span>"}},e=function(a){a=Elm.JavaScript.castStringToJSString(a);return b("font-family",a)},i=c("h1"),a=b("font-style","italic"),c=c("b"),j=b("text-decoration","underline"),l=b("text-decoration","overline"),n=b("text-decoration","line-through");return{fromString:d,toText:d,header:i,
+height:function(a){return b("font-size",a+"em")},italic:a,bold:c,underline:j,overline:l,strikeThrough:n,monospace:e("monospace"),typeface:e,color:function(a){return b("color",Elm.Color.extract(a))},link:function(b){return function(a){return"<a href='"+d(b)+"'>"+a+"</a>"}}}}();
+var Render=function(){function d(b){b=document.createElement(b);b.style.padding="0";b.style.margin="0";return b}function c(b){return b}function b(b){b.style.styleFloat="left";b.style.cssFloat="left";return b}function e(b){b.style.position="absolute";return b}function i(b,a,c){for(var e=d("div"),k=c.length;k--;){var i=b(a(c[k]));e.appendChild(i)}return e}function a(b){switch(b[0]){case "Absolute":return b[1]+"px";case "Relative":return 100*b[1]+"%"}}function j(b,c){c.style.position="absolute";c.style.margin=
+"auto";switch(b[0]){case "Position":"Far"!==b[1][0]&&(c.style.left=0);"Near"!==b[1][0]&&(c.style.right=0);"Far"!==b[2][0]&&(c.style.top=0);"Near"!==b[2][0]&&(c.style.bottom=0);break;case "PositionAt":c.style.top=a(b[2]);c.style.left=a(b[1]);var g="translate("+~~(-c.style.width.slice(0,-2)/2)+"px,"+~~(-c.style.height.slice(0,-2)/2)+"px)";c.style.transform=g;c.style.msTransform=g;c.style.MozTransform=g;c.style.webkitTransform=g;c.style.OTransform=g;break;default:g=b[0].slice(-2),c.style["T"===g[0]?
+"top":"bottom"]=a(b[2]),c.style["L"===g[1]?"left":"right"]=a(b[1])}}function l(a){var f={};switch(a[2][0]){case "EText":var f=a[2][1],g=a[2][2],s=d("div");s.innerHTML=g;s.style.textAlign=f;f=s;break;case "EImage":f=a[2][1];g=d("img");g.src=f;g.name=f;g.style.display="block";f=g;break;case "EVideo":s=a[2][1];f=d("video");f.controls="controls";g=d("source");g.src=s;s=s.split(".");g.type="video/"+s[s.length-1];f.appendChild(g);f.style.display="block";break;case "EFittedImage":var k=a[3],p=a[4],f=a[2][1],
+g=d("div");g.style.width=k+"px";g.style.height=p+"px";g.style.position="relative";g.style.overflow="hidden";var m=d("img");m.onload=function(){m.style.position="absolute";m.style.margin="auto";var b=k,a=p;k/p>this.width/this.height?a=Math.round(this.height*k/this.width):b=Math.round(this.width*p/this.height);m.style.width=b+"px";m.style.height=a+"px";m.style.left=(k-b)/2+"px";m.style.top=(p-a)/2+"px"};m.src=f;m.name=f;g.appendChild(m);f=g;break;case "EFlow":a:{f=a[2][2];switch(a[2][1][0]){case "DDown":f=
+f.slice(0).reverse();case "DUp":f=i(c,l,f);break a;case "DRight":f=f.slice(0).reverse();case "DLeft":f=i(b,l,f);break a;case "DOut":f=f.slice(0).reverse();case "DIn":f=i(e,l,f);break a}f=void 0}break;case "ECollage":f=Collage.collage(a[2][1],a[2][2],a[2][3]);break;case "EEmpty":f=d("div");break;case "EContainer":g=a[2][1];f=l(a[2][2]);j(g,f);g=d("div");g.style.position="relative";g.style.overflow="hidden";g.appendChild(f);f=g;break;case "EHtml":f=a[2][1];"button"!==f.type&&(g=Value.getExcess(f),a[3]-=
+g[0],a[4]-=g[1]);break;case "EExternalHtml":f=d("div"),f.appendChild(a[2][1])}f.id=a[1];f.style.width=~~a[3]+"px";f.style.height=~~a[4]+"px";1!==a[5]&&(f.style.opacity=a[5]);"Just"===a[6][0]&&(f.style.backgroundColor=Elm.Color.extract(a[6][1]));return"Just"===a[7][0]?(g=d("a"),g.href=a[7][1],g.appendChild(f),g):f}function n(a,f,g){"A"===a.tagName&&(a=a.firstChild);if(f[1]!==g[1]){if(f[2][0]!==g[2][0])return a.parentNode.replaceChild(l(g),a);var d=g[2],k=f[2];switch(d[0]){case "EText":d[1]!==k[1]&&
+(a.style.textAlign=d[1]);d[2]!==k[2]&&(a.innerHTML=d[2]);break;case "EImage":d[1]!==k[1]&&(a.src=d[1]);break;case "EVideo":case "EFittedImage":if(!Value.eq(d,k)||g[3]!==f[3]||g[4]!==f[4])return a.parentNode.replaceChild(l(g),a);break;case "ECollage":if(d[1]!==k[1]||d[2]!==k[2]||d[3].length!==k[3].length)return a.parentNode.replaceChild(l(g),a);Collage.updateCollage(a,k[3],d[3]);break;case "EFlow":if(d[1]!==k[1])return a.parentNode.replaceChild(l(g),a);var i=d[2],m=a.childNodes;if(i.length!==m.length)return a.parentNode.replaceChild(l(g),
+a);var k=k[2],x=function(a){return a};switch(d[1][0]){case "DDown":case "DUp":x=c;break;case "DRight":case "DLeft":x=b;break;case "DOut":case "DIn":x=e}for(d=m.length;d--;)n(m[d],k[d],i[d]),x(m[d]);break;case "EContainer":n(a.childNodes[0],k[2],d[2]);j(d[1],a.childNodes[0]);break;case "EHtml":g[1]!==f[1]&&(i=l(g),a.parentNode.replaceChild(i,a),a=i);"button"!==i.type&&(d=Value.getExcess(a),g[3]-=d[0],g[4]-=d[1]);break;case "EExternalHtml":g[1]!==f[1]&&a.parentNode.replaceChild(l(g),a)}g[3]!==f[3]&&
+(a.style.width=~~g[3]+"px");g[4]!==f[4]&&(a.style.height=~~g[4]+"px");g[5]!==f[5]&&(a.style.opacity=g[5]);2===g[6].length&&(d=Elm.Color.extract(g[6][1]),d!==a.style.backgroundColor&&(a.style.backgroundColor=d));if(2===g[7].length&&(1===f[7].length||g[7][1]!==f[7][1]))a.parentNode.href=g[7][1];g[1]=f[1]}}return{render:l,update:n,addTo:function(a,b){a.appendChild(b)},newElement:d,flowWith:i,goIn:e}}();
+Elm.Signal=function(){function d(a){this.id=Guid.guid();this.value=a;this.kids=[];this.defaultNumberOfKids=0;this.recv=function(a,b,c){if(b=b===this.id)this.value=c;n(this,a,b);return b};Dispatcher.inputs.push(this)}function c(a,b){this.id=Guid.guid();this.value=null;this.kids=[];this.count=0;this.changed=!1;b.reverse();this.recalc=function(){for(var c=a,e=b.length;e--;)c=c(b[e].value);this.value=c};this.recalc();this.recv=function(a,c){this.count+=1;c&&(this.changed=!0);this.count==b.length&&(this.changed&&
+this.recalc(),n(this,a,this.changed),this.changed=!1,this.count=0)};for(var c=b.length;c--;)b[c].kids.push(this)}function b(a,b,c,e){this.id=Guid.guid();this.value=c?b(e.value):b;this.kids=[];this.recv=function(b,c){c&&(this.value=a(e.value)(this.value));n(this,b,c)};e.kids.push(this)}function e(a,b,c){this.id=Guid.guid();this.value=a(c.value)?b:c.value;this.kids=[];this.recv=function(b,e){var g=e&&!a(c.value);g&&(this.value=c.value);n(this,b,g)};c.kids.push(this)}function i(a){this.id=Guid.guid();
+this.value=a.value;this.kids=[];this.recv=function(b,c){var e=c&&!Value.eq(this.value,a.value);e&&(this.value=a.value);n(this,b,e)};a.kids.push(this)}function a(a,b){this.id=Guid.guid();var c=(new window.Date).getTime();this.value=a?Value.Tuple(c,b.value):c;this.kids=[];this.recv=function(c,e){e&&(this.value=a?Value.Tuple(c,b.value):c);n(this,c,e)};b.kids.push(this)}function j(a,b){this.id=Guid.guid();this.value=b.value;this.kids=[];this.count=0;this.changed=!1;this.recv=function(c,e,d){d===a.id&&
+(this.changed=e);this.count+=1;2==this.count&&(this.changed&&(this.value=b.value),n(this,c,this.changed),this.count=0,this.changed=!1)};a.kids.push(this);b.kids.push(this)}function l(a,b){this.id=Guid.guid();this.value=a.value;this.kids=[];this.next=null;this.count=0;this.changed=!1;this.recv=function(c,e,d){this.count+=1;e&&(this.changed=!0,d==b.id&&null===this.next&&(this.next=b.value),d==a.id&&(this.next=a.value));2==this.count&&(this.changed&&(this.value=this.next,this.next=null),n(this,c,this.changed),
+this.changed=!1,this.count=0)};a.kids.push(this);b.kids.push(this)}var n=function(a,b,c){for(var e=a.kids,d=e.length;d--;)e[d].recv(b,c,a.id)},h=function(a){return function(b){return function(d){d=new c(function(a){return function(b){return[a,b]}},[a,d]);d=new e(function(a){return a[0]},[!0,b],d);return new c(function(a){return a[1]},[d])}}};return{constant:function(a){return new d(a)},lift:function(a){return function(b){return new c(a,[b])}},lift2:function(a){return function(b){return function(e){return new c(a,
+[b,e])}}},lift3:function(a){return function(b){return function(e){return function(d){return new c(a,[b,e,d])}}}},lift4:function(a){return function(b){return function(e){return function(d){return function(h){return new c(a,[b,e,d,h])}}}}},lift5:function(a){return function(b){return function(e){return function(d){return function(h){return function(i){return new c(a,[b,e,d,h,i])}}}}}},lift6:function(a){return function(b){return function(e){return function(d){return function(h){return function(i){return function(l){return new c(a,
+[b,e,d,h,i,l])}}}}}}},lift7:function(a){return function(b){return function(e){return function(d){return function(h){return function(i){return function(l){return function(j){return new c(a,[b,e,d,h,i,l,j])}}}}}}}},lift8:function(a){return function(b){return function(e){return function(d){return function(h){return function(i){return function(l){return function(j){return function(n){return new c(a,[b,e,d,h,i,l,j,n])}}}}}}}}},foldp:function(a){return function(c){return function(e){return new b(a,c,!1,
+e)}}},foldp_:function(a){return function(c){return function(e){return new b(a,c,!0,e)}}},foldp1:function(a){return function(c){return new b(a,function(a){return a},!0,c)}},delay:function(a){return function(b){var e=new d(b.value),h=!0,b=new j(e,new c(function(a){return function(){return a}},[e,new c(function(b){h||setTimeout(function(){Dispatcher.notify(e.id,b)},a)},[b])])),h=!1;return b}},merge:function(a){return function(b){return new l(a,b)}},merges:function(a){return Elm.List.foldl1(function(a){return function(b){return new l(a,
+b)}})(a)},average:function(a){return function(b){for(var e=Array(a),d=a;d--;)e[d]=0;var d=0,h=!1,i=0;return new c(function(b){i+=b-e[d];e[d]=b;b=i/Math.max(1,h?a:d);++d==a&&(h=!0,d=0);return b},[b])}},count:function(a){return new b(function(){return function(a){return a+1}},0,!1,a)},countIf:function(a){return function(c){return new b(function(b){return function(c){return a(b)?c+1:c}},0,!1,c)}},keepIf:function(a){return function(b){return function(c){return new e(function(b){return!a(b)},b,c)}}},dropIf:function(a){return function(b){return function(c){return new e(a,
+b,c)}}},keepWhen:function(a){return h(new c(function(a){return!a},[a]))},dropWhen:h,dropRepeats:function(a){return new i(a)},sampleOn:function(a){return function(b){return new j(a,b)}},timestamp:function(b){return new a(!0,b)},timeOf:function(b){return new a(!1,b)}}}();
+var Dispatcher=function(){function d(b){if(!b.hasOwnProperty("defaultNumberOfKids"))return!0;var a=b.kids.length;if(0==a)return!1;if(a>b.defaultNumberOfKids)return!0;for(var c=!1;a--;)c=c||d(b.kids[a]);return c}var c=null,b=[],e=null;return{initialize:function(){c=Elm.main();c.hasOwnProperty("recv")||(c=Elm.Signal.constant(c));e=c.value;for(var i=[],a=b.length;a--;)d(b[a])&&i.push(b[a]);b=i;document.getElementById("content").appendChild(Render.render(e));i=document.getElementById("widthChecker").offsetWidth;
+i!==window.innerWidth&&Dispatcher.notify(Elm.Window.dimensions.id,Value.Tuple(i,window.innerHeight));c=Elm.Signal.lift(function(a){var b=document.getElementById("content");Render.update(b.firstChild,e,a);return e=a})(c)},notify:function(c,a){for(var e=(new window.Date).getTime(),d=!1,n=b.length;n--;)d=b[n].recv(e,c,a)||d;return d},inputs:b}}();
+Elm.HTTP=function(){function d(b){return function(c){return function(e){return function(d){return{"0":"Request",length:1,verb:a.castStringToJSString(b),url:a.castStringToJSString(c),data:null===e?null:a.castStringToJSString(e),headers:d}}}}}function c(a){return d("GET")(a)(null)(["Nil"])}function b(b,c){return function(d){if(""!==d.url){var f={value:["Waiting"]};b.push(f);var g=null;window.ActiveXObject&&(g=new ActiveXObject("Microsoft.XMLHTTP"));window.XMLHttpRequest&&(g=new XMLHttpRequest);g.onreadystatechange=
+function(){4===g.readyState&&(f.value=200===g.status?["Success",j(g.responseText)]:["Failure",g.status,j(g.statusText)],setTimeout(function(){e(b,c)},0))};g.open(d.verb,d.url,!0);Elm.List.map(function(b){g.setRequestHeader(a.castStringToJSString(b[1]),a.castStringToJSString(b[2]))})(d.headers);g.send(d.data)}}}function e(a,b){0<a.length&&(Dispatcher.notify(b.id,a[0].value),"Waiting"!==a[0].value[0]&&(a.shift(),setTimeout(function(){e(a,b)},0)))}function i(a){var c=Elm.Signal.constant(["Waiting"]),
+a=Elm.Signal.lift(b([],c))(a);return Elm.Signal.lift2(function(a){return function(){return a}})(c)(a)}var a=Elm.JavaScript,j=Elm.JavaScript.castJSStringToString;return{get:c,post:function(a){return function(b){return d("POST")(a)(b)(["Nil"])}},request:d,send:i,sendGet:function(a){return i(Elm.Signal.lift(c)(a))}}}();
+Elm.Input=function(){var d=Elm.JavaScript,c=Elm.JavaScript.castJSStringToString,b=function(a,b){a.placeholder=d.castStringToJSString(b);var e=Elm.Signal.constant(["Nil"]);Value.addListener(a,"keyup",function(){Dispatcher.notify(e.id,c(a.value));a.focus()});a.style.padding="1px";return Value.Tuple(Value.wrap(a),e)},e=function(a){a=document.createElement(a);a.style.padding="0";a.style.margin="0";return a},i=function(a){for(var b=e("select"),c=[];"Cons"===a[0];){var d=e("option"),h=Value.toText(a[1][1]);
+d.value=h;d.innerHTML=h;b.appendChild(d);c.push(a[1][2]);a=a[2]}var f=Elm.Signal.constant(c[0]);Value.addListener(b,"change",function(){Dispatcher.notify(f.id,c[b.selectedIndex])});return Value.Tuple(Value.wrap(b),f)};return{textArea:function(a){return function(c){var d=e("textarea");d.rows=c;d.cols=a;return b(d,"")}},textField:function(a){var c=e("input");c.type="text";return b(c,a)},password:function(a){var c=e("input");c.type="password";return b(c,a)},checkbox:function(a){var b=e("input");b.type=
+"checkbox";b.checked=a;var c=Elm.Signal.constant(a);Value.addListener(b,"change",function(){Dispatcher.notify(c.id,b.checked)});return Value.Tuple(Value.wrap(b),c)},dropDown:i,stringDropDown:function(a){return i(Elm.List.map(function(a){return Value.Tuple(a,a)})(a))},button:function(a){var b=e("input");b.type="button";b.value=d.castStringToJSString(a);var c=Elm.Signal.constant(!1);Value.addListener(b,"click",function(){Dispatcher.notify(c.id,!0);Dispatcher.notify(c.id,!1)});return Value.Tuple(Value.wrap(b),
+c)}}}();
+Elm.Keyboard={Raw:function(){function d(b,c){return"Nil"===c[0]?c:c[1]===b?c[2]:["Cons",c[1],d(b,c[2])]}var c=Elm.Signal.constant(["Nil"]),b=Elm.Signal.constant(["Nothing"]);Value.addListener(document,"keydown",function(b){var d;a:{for(d=c.value;"Nil"!==d[0];){if(d[1]===b.keyCode){d=!0;break a}d=d[2]}d=!1}d||Dispatcher.notify(c.id,["Cons",b.keyCode,c.value])||this.removeEventListener("keydown",arguments.callee,!1)});Value.addListener(document,"keyup",function(b){var i=d(b.keyCode,c.value);Dispatcher.notify(c.id,
+i)||this.removeEventListener("keyup",arguments.callee,!1)});Value.addListener(window,"blur",function(b){Dispatcher.notify(c.id,["Nil"])||this.removeEventListener("blur",arguments.callee,!1)});Value.addListener(document,"keypress",function(c){var d=Dispatcher.notify(b.id,["Just",c.charCode||c.keyCode]);Dispatcher.notify(b.id,["Nothing"]);d||this.removeEventListener("keypress",arguments.callee,!1)});return{keysDown:c,charPressed:b}}()};
+Elm.Mouse=function(){function d(a){var b=0,c=0;a||(a=window.event);if(a.pageX||a.pageY)b=a.pageX,c=a.pageY;else if(a.clientX||a.clientY)b=a.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,c=a.clientY+document.body.scrollTop+document.documentElement.scrollTop;return Value.Tuple(b,c)}var c=Elm.Signal.constant(Value.Tuple(0,0));c.defaultNumberOfKids=2;var b=Elm.Signal.lift(function(a){return a[1]})(c);b.defaultNumberOfKids=0;var e=Elm.Signal.lift(function(a){return a[2]})(c);e.defaultNumberOfKids=
+0;var i=Elm.Signal.constant(!1),a=Elm.Signal.constant(!1),j=Elm.Signal.constant(Value.Tuple());Value.addListener(document,"click",function(b){var c=Dispatcher.notify(a.id,!0),d=Dispatcher.notify(j.id,Value.Tuple());Dispatcher.notify(a.id,!1);!c&&!d&&this.removeEventListener("click",arguments.callee,!1)});Value.addListener(document,"mousedown",function(a){Dispatcher.notify(i.id,!0)||this.removeEventListener("mousedown",arguments.callee,!1)});Value.addListener(document,"mouseup",function(a){Dispatcher.notify(i.id,
+!1)||this.removeEventListener("mouseup",arguments.callee,!1)});Value.addListener(document,"mousemove",function(a){Dispatcher.notify(c.id,d(a))||this.removeEventListener("mousemove",arguments.callee,!1)});return{position:c,x:b,y:e,isClicked:a,isDown:i,clicks:j,isClickedOn:function(a){var a=Render.render(a),b=Elm.Signal.constant(!1);Value.addListener(a,"click",function(){Dispatcher.notify(b.id,!0);Dispatcher.notify(b.id,!1)});return Value.Tuple(Value.wrap(a),b)}}}();
+Elm.Random=function(){return{inRange:function(d){return function(c){return Elm.Signal.constant(Math.floor(Math.random()*(c-d+1))+d)}},randomize:function(d){return function(c){return function(b){return Elm.Signal.lift(function(){return Math.floor(Math.random()*(c-d+1))+d})(b)}}}}}();
+Elm.Time=function(){function d(){return(new window.Date).getTime()}function c(b){return function(c){var i=1E3/b,a=d(),j=a,l=0,n=!0,h=Elm.Signal.constant(l),f=0;return Elm.Signal.lift2(function(b){return function(c){if(b){var e=!n&&b;f=setTimeout(function(){j=d();l=e?0:j-a;a=j;Dispatcher.notify(h.id,l)},i)}else n&&clearTimeout(f);n=b;return c}})(c)(h)}}Elm.Signal.constant(!0);return{fpsWhen:c,fps:function(b){return c(b)(Elm.Signal.constant(!0))},every:function(b){var c=Elm.Signal.constant(d());setInterval(function(){Dispatcher.notify(c.id,
+d())},b);return c},delay:Elm.Signal.delay,since:function(b){return function(c){var d=Elm.Signal.count(Elm.Signal.delay(b)(c));return Elm.Signal.lift2(function(a){return function(b){return!Value.eq(a,b)}})(Elm.Signal.count(c))(d)}},after:function(b){var b=1E3*b,c=Elm.Signal.constant(!1);setTimeout(function(){Dispatcher.notify(c.id,!0)},b);return c},before:function(b){var b=1E3*b,c=Elm.Signal.constant(!0);setTimeout(function(){Dispatcher.notify(c.id,!1)},b);return c},hour:36E5,minute:6E4,second:1E3,
+ms:1,inHours:function(b){return b/36E5},inMinutes:function(b){return b/6E4},inSeconds:function(b){return b/1E3},inMss:function(b){return b},toDate:function(b){return new window.Date(b)},read:function(b){b=window.Date.parse(b);return isNaN(b)?["Nothing"]:["Just",b]}}}();
+Elm.Window=function(){var d=Elm.Signal.constant(Value.Tuple(window.innerWidth,window.innerHeight));d.defaultNumberOfKids=2;var c=Elm.Signal.lift(function(b){return b[1]})(d);c.defaultNumberOfKids=0;var b=Elm.Signal.lift(function(b){return b[2]})(d);b.defaultNumberOfKids=0;Value.addListener(window,"resize",function(b){var c=document.getElementById("widthChecker").offsetWidth;Dispatcher.notify(d.id,Value.Tuple(c,window.innerHeight))||this.removeEventListener("resize",arguments.callee,!1)});return{dimensions:d,
+width:c,height:b}}();
+Elm.Date=function(){var d="Sun Mon Tue Wed Thu Fri Sat".split(" "),c="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ");return{read:function(b){b=new window.Date(Elm.JavaScript.castStringToJSString(b));return isNaN(b.getTime())?["Nothing"]:["Just",b]},year:function(b){return b.getFullYear()},month:function(b){return[c[b.getMonth()]]},day:function(b){return b.getDate()},hour:function(b){return b.getHours()},minute:function(b){return b.getMinutes()},second:function(b){return b.getSeconds()},dayOfWeek:function(b){return[d[b.getDay()]]},
+toTime:function(b){return b.getTime()},Mon:["Mon"],Tue:["Tue"],Wed:["Wed"],Thu:["Thu"],Fri:["Fri"],Sat:["Sat"],Sun:["Sun"],Jan:["Jan"],Feb:["Feb"],Mar:["Mar"],Apr:["Apr"],May:["May"],Jun:["Jun"],Jul:["Jul"],Aug:["Aug"],Sep:["Sep"],Oct:["Oct"],Nov:["Nov"],Dec:["Dec"]}}();Value.addListener(document,"elm_log",function(d){console.log(d.value)});Value.addListener(document,"elm_title",function(d){document.title=d.value});
+Value.addListener(document,"elm_redirect",function(d){0<d.value.length&&(window.location=d.value)});
+Elm.Prelude=function(){var d=function(c){return function(b){var e=c%b,e=0==c?0:0<b?0<=c?e:e+b:-d(-c)(-b);return e==b?0:e}};return{eq:Value.eq,id:function(c){return c},not:function(c){return!c},fst:function(c){return c[1]},snd:function(c){return c[2]},rem:function(c){return function(b){return c%b}},div:function(c){return function(b){return~~(c/b)}},otherwise:!0,compare:function(c){return function(b){if(c instanceof Array&&b instanceof Array){var d=c.length;if(d==b.length){for(var i=0;i<d;++i){var a=
+compare(c[i])(b[i]);if("EQ"!==a[0])return a}return["EQ"]}}return[c===b?"EQ":c<b?"LT":"GT"]}},toFloat:function(c){return c},round:function(c){return Math.round(c)},floor:function(c){return Math.floor(c)},ceiling:function(c){return Math.ceil(c)},truncate:function(c){return~~c},readInt:function(c){var c=Elm.JavaScript.castStringToJSString(c),b=c.length;if(0===b)return["Nothing"];var d=0;if("-"==c[0]){if(1===b)return["Nothing"];d=1}for(;d<b;++d)if(!Char.isDigit(c[d]))return["Nothing"];return["Just",parseInt(c)]},
+readFloat:function(c){var c=Elm.JavaScript.castStringToJSString(c),b=c.length;if(0===b)return["Nothing"];var d=0;if("-"==c[0]){if(1===b)return["Nothing"];d=1}for(var i=0;d<b;++d)if(!Char.isDigit(c[d])){if("."===c[d]&&(i+=1,1>=i))continue;return["Nothing"]}return["Just",parseFloat(c)]},sqrt:Math.sqrt,abs:Math.abs,pi:Math.PI,e:Math.E,sin:Math.sin,cos:Math.cos,tan:Math.tan,asin:Math.asin,acos:Math.acos,atan:Math.atan,atan2:function(c){return function(b){return Math.atan2(c,b)}},mod:d,min:function(c){return function(b){return Math.min(c,
+b)}},max:function(c){return function(b){return Math.max(c,b)}},flip:function(c){return function(b){return function(d){return c(d)(b)}}},clamp:function(c){return function(b){return function(d){return Math.min(b,Math.max(c,d))}}},curry:function(c){return function(b){return function(d){return c(["Tuple2",b,d])}}},uncurry:function(c){return function(b){if("Tuple2"!==b[0])throw"Function was uncurry'd but was not given a pair.";return c(b[1])(b[2])}},logBase:function(c){return function(b){return Math.log(b)/
+Math.log(c)}},Just:Elm.Maybe.Just,Nothing:Elm.Maybe.Nothing,maybe:Elm.Maybe.maybe,map:Elm.List.map,zip:Elm.List.zip,zipWith:Elm.List.zipWith,filter:Elm.List.filter,head:Elm.List.head,tail:Elm.List.tail,last:Elm.List.last,length:Elm.List.length,reverse:Elm.List.reverse,foldr:Elm.List.foldr,foldr1:Elm.List.foldr1,foldl:Elm.List.foldl,foldl1:Elm.List.foldl1,and:Elm.List.and,or:Elm.List.or,all:Elm.List.all,any:Elm.List.any,sum:Elm.List.sum,product:Elm.List.product,concat:Elm.List.concat,concatMap:Elm.List.concatMap,
+maximum:Elm.List.maximum,minimum:Elm.List.minimum,scanl:Elm.List.scanl,scanl1:Elm.List.scanl1,take:Elm.List.take,drop:Elm.List.drop,zip:Elm.List.zip,unzip:Elm.List.unzip,lift:Elm.Signal.lift,lift2:Elm.Signal.lift2,lift3:Elm.Signal.lift3,lift4:Elm.Signal.lift4,lift5:Elm.Signal.lift5,lift6:Elm.Signal.lift6,lift7:Elm.Signal.lift7,lift8:Elm.Signal.lift8,foldp:Elm.Signal.foldp,foldp1:Elm.Signal.foldp1,foldp_:Elm.Signal.foldp_,constant:Elm.Signal.constant,merge:Elm.Signal.merge,count:Elm.Signal.count,countIf:Elm.Signal.countIf,
+average:Elm.Signal.average,keepIf:Elm.Signal.keepIf,dropIf:Elm.Signal.dropIf,keepWhen:Elm.Signal.keepWhen,dropWhen:Elm.Signal.dropWhen,dropRepeats:Elm.Signal.dropRepeats,sampleOn:Elm.Signal.sampleOn,timestamp:Elm.Signal.timestamp,timeOf:Elm.Signal.timeOf}}();(function(){var d=function(c){for(var b in c)Elm.Prelude[b]=c[b]};d(Elm.Color);d(Elm.Text);d(Elm.Graphics);d(Elm.Time);show=Value.show})();
+Elm.Dict=function(){function d(a){return function(b){return function(c){return function(d){return function(e){return["RBNode",a,b,c,d,e]}}}}}function c(a){return function(){switch(a[0]){case "RBEmpty":return z(Value.str("(min RBEmpty) is not defined"));case "RBNode":switch(a[4][0]){case "RBEmpty":return["Tuple2",a[2],a[3]]}return c(a[4])}throw"Non-exhaustive pattern match in case";}()}function b(a){return function(c){var d;a:{switch(c[0]){case "RBEmpty":d=Nothing;break a;case "RBNode":d=function(){switch(compare(a)(c[2])[0]){case "EQ":return Just(c[3]);
+case "GT":return b(a)(c[5]);case "LT":return b(a)(c[4])}throw"Non-exhaustive pattern match in case";}();break a}throw"Non-exhaustive pattern match in case";}return d}}function e(a){return function(b){return function(c){var d;a:{switch(c[0]){case "RBEmpty":d=a;break a;case "RBNode":d=function(){switch(compare(b)(c[2])[0]){case "EQ":return c[3];case "GT":return e(a)(b)(c[5]);case "LT":return e(a)(b)(c[4])}throw"Non-exhaustive pattern match in case";}();break a}throw"Non-exhaustive pattern match in case";
+}return d}}}function i(a){return function(c){return q(b(a)(c))}}function a(a){a:{switch(a[0]){case "RBNode":switch(a[5][0]){case "RBNode":a=d(a[1])(a[5][2])(a[5][3])(d(r)(a[2])(a[3])(a[4])(a[5][4]))(a[5][5]);break a}}a=z(Value.str("rotateLeft of a node without enough children"))}return a}function j(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":a=d(a[1])(a[4][2])(a[4][3])(a[4][4])(d(r)(a[2])(a[3])(a[4][5])(a[5]));break a}}a=z(Value.str("rotateRight of a node without enough children"))}return a}
+function l(a){a:{switch(a[0]){case "Black":a=r;break a;case "Red":a=v;break a}throw"Non-exhaustive pattern match in case";}return a}function n(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[5][0]){case "RBNode":a=d(l(a[1]))(a[2])(a[3])(d(l(a[4][1]))(a[4][2])(a[4][3])(a[4][4])(a[4][5]))(d(l(a[5][1]))(a[5][2])(a[5][3])(a[5][4])(a[5][5]));break a}}}a=z(Value.str("color_flip called on a RBEmpty or RBNode with a RBEmpty child"))}return a}function h(b){a:switch(b[0]){case "RBNode":switch(b[5][0]){case "RBNode":switch(b[5][1][0]){case "Red":b=
+a(b);break a}}}a:switch(b[0]){case "RBNode":switch(b[4][0]){case "RBNode":switch(b[4][1][0]){case "Red":switch(b[4][4][0]){case "RBNode":switch(b[4][4][1][0]){case "Red":b=j(b);break a}}}}}a:switch(b[0]){case "RBNode":switch(b[4][0]){case "RBNode":switch(b[4][1][0]){case "Red":switch(b[5][0]){case "RBNode":switch(b[5][1][0]){case "Red":b=n(b);break a}}}}}return b}function f(a){a:switch(a[0]){case "RBNode":switch(a[1][0]){case "Red":a=d(v)(a[2])(a[3])(a[4])(a[5]);break a}}return a}function g(a){return function(b){return function(c){var e=
+function(c){var f;a:{switch(c[0]){case "RBEmpty":f=d(r)(a)(b)(w)(w);break a;case "RBNode":f=function(){switch(compare(a)(c[2])[0]){case "EQ":return d(c[1])(c[2])(b)(c[4])(c[5]);case "GT":return d(c[1])(c[2])(c[3])(c[4])(e(c[5]));case "LT":return d(c[1])(c[2])(c[3])(e(c[4]))(c[5])}throw"Non-exhaustive pattern match in case";}();f=h(f);break a}throw"Non-exhaustive pattern match in case";}return f};return f(e(c))}}}function s(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][1][0]){case "Red":a=
+!0;break a}}}a=!1}return a}function k(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBNode":switch(a[4][4][0]){case "RBNode":switch(a[4][4][1][0]){case "Red":a=!0;break a}}}}a=!1}return a}function p(b){if(not(s(b))&&not(k(b))){b=n(b);a:switch(b[0]){case "RBNode":b:switch(b[5][0]){case "RBNode":switch(b[5][4][0]){case "RBNode":switch(b[5][4][1][0]){case "Red":b=n(a(d(b[1])(b[2])(b[3])(b[4])(j(b[5]))));break b}}}break a}}return b}function m(a){return function(b){var e;a:{switch(b[0]){case "RBEmpty":e=
+w;break a;case "RBNode":if("LT"===compare(a)(b[2])[0]){e=p(b);b:{switch(e[0]){case "RBEmpty":e=z(Value.str("delLT on RBEmpty"));break b;case "RBNode":e=h(d(e[1])(e[2])(e[3])(del(e[4]))(e[5]));break b}break}}else{b=s(b)?j(b):b;b:{switch(b[0]){case "RBNode":switch(b[5][0]){case "RBEmpty":b=eq(a,b[2]);break b}}b=!1}if(b)e=w;else{var b=not,g;b:{switch(e[0]){case "RBNode":switch(e[5][0]){case "RBNode":switch(e[5][1][0]){case "Red":g=!0;break b}}}g=!1}if(b=b(g)){b=not;b:{switch(e[0]){case "RBNode":switch(e[5][0]){case "RBNode":switch(e[5][4][0]){case "RBNode":switch(e[5][4][1][0]){case "Red":g=
+!0;break b}}}}g=!1}b=b(g)}b&&(e=n(e),e=k(e)?n(j(e)):e);b:{switch(e[0]){case "RBNode":b=eq(a,e[2]);break b}b=!1}if(b)b:{switch(e[0]){case "RBEmpty":e=z(Value.str("delEQ called on a RBEmpty"));break b;case "RBNode":g=c(e[5]);c:{switch(g[0]){case "Tuple2":b=g[1];break c}break}c:{switch(g[0]){case "Tuple2":g=g[2];break c}break}var b=d(e[1])(b)(g)(e[4]),i=function(a){a:{switch(a[0]){case "RBNode":switch(a[4][0]){case "RBEmpty":a=w;break a}}a=p(a);b:{switch(a[0]){case "RBEmpty":a=w;break b;case "RBNode":a=
+h(d(a[1])(a[2])(a[3])(i(a[4]))(a[5]));break b}throw"Non-exhaustive pattern match in case";}}return a};e=f(i(e[5]));e=h(b(e));break b}break}else b:{switch(e[0]){case "RBEmpty":e=z(Value.str("delGT called on a RBEmpty"));break b;case "RBNode":e=h(d(e[1])(e[2])(e[3])(e[4])(del(e[5])));break b}break}}}break a}throw"Non-exhaustive pattern match in case";}return f(e)}}function x(a){return function(b){a:{switch(b[0]){case "RBEmpty":b=w;break a;case "RBNode":b=d(b[1])(b[2])(a(b[3]))(x(a)(b[4]))(x(a)(b[5]));
+break a}throw"Non-exhaustive pattern match in case";}return b}}function u(a){return function(b){return function(c){a:{switch(c[0]){case "RBEmpty":c=b;break a;case "RBNode":c=u(a)(a(c[2])(c[3])(u(a)(b)(c[4])))(c[5]);break a}throw"Non-exhaustive pattern match in case";}return c}}}function t(a){return function(b){return function(c){a:{switch(c[0]){case "RBEmpty":c=b;break a;case "RBNode":c=t(a)(a(c[2])(c[3])(t(a)(b)(c[5])))(c[4]);break a}throw"Non-exhaustive pattern match in case";}return c}}}for(this.i in Elm.Prelude)eval("var "+
+this.i+"=Elm.Prelude[this.i];");var q=Elm.Maybe.isJust,r=["Red"],v=["Black"],w=["RBEmpty"],y=w,z=function(a){return a};return{empty:y,lookup:b,findWithDefault:e,member:i,insert:g,singleton:function(a){return function(b){return g(a)(b)(w)}},remove:m,map:x,foldl:u,foldr:t,union:function(a){return function(b){return u(g)(b)(a)}},intersect:function(a){return function(b){return u(function(a){return function(c){return function(d){return i(a)(b)?g(a)(c)(d):d}}})(y)(a)}},diff:function(a){return function(b){return u(function(a){return function(){return function(b){return m(a)(b)}}})(a)(b)}},
+keys:function(a){return u(function(a){return function(){return function(b){return["Cons",a,b]}}})(["Nil"])(a)},values:function(a){return u(function(){return function(a){return function(b){return["Cons",a,b]}}})(["Nil"])(a)},toList:function(a){return u(function(a){return function(b){return function(c){return["Cons",["Tuple2",a,b],c]}}})(["Nil"])(a)},fromList:function(a){return List.foldl(uncurry(g))(y)(a)}}}();
+Elm.Set=function(){var d=Elm.Dict.empty,c=Elm.Dict.remove,b=Elm.Dict.member,e=Elm.Dict.union,i=Elm.Dict.intersect,a=Elm.Dict.diff,j=Elm.Dict.keys,l=Elm.List.foldl(function(a){return function(b){return Elm.Dict.insert(a)(["Tuple0"])(b)}})(d);return{empty:d,singleton:function(a){return Elm.Dict.singleton(a)(["Tuple0"])},insert:function(a){return Elm.Dict.insert(a)(["Tuple0"])},remove:c,member:b,union:e,intersect:i,diff:a,toList:j,fromList:l,foldl:function(a){return Elm.Dict.foldl(function(b){return function(){return function(c){return a(b)(c)}}})},
+foldr:function(a){return Elm.Dict.foldr(function(b){return function(){return function(c){return a(b)(c)}}})},map:function(a){return function(b){b=j(b);return l(Elm.List.map(a)(b))}}}}();
+(function(){try{var d={};for(this.i in Elm)eval("var "+this.i+"=Elm[this.i];");if(Elm.Automaton)throw"Module name collision, 'Automaton' is already defined.";Elm.Automaton=function(){function b(a){return["Automaton",a]}function c(a){return b(function(b){var d=unzip(map(function(a){a:{switch(a[0]){case "Automaton":a=a[1](b);break a}throw"Non-exhaustive pattern match in case";}return a})(a)),f;a:{switch(d[0]){case "Tuple2":f=d[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(d[0]){case "Tuple2":d=
+d[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",f,c(d)]})}function i(a){return b(function(b){return["Tuple2",a(b),i(a)]})}function a(c){return function(d){return b(function(b){b=d(b)(c);return["Tuple2",b,a(b)(d)]})}}function j(a){return function(c){return b(function(b){var d=c(b)(a);a:{switch(d[0]){case "Tuple2":b=d[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(d[0]){case "Tuple2":d=d[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",
+b,j(d)(c)]})}}function l(a){return function(b){a:{switch(a[0]){case "Tuple2":b:{switch(b[0]){case "Tuple2":b=["Tuple2",a[1]-b[1],a[2]-b[2]];break b}break}break a}throw"Non-exhaustive pattern match in case";}return b}}function n(a){return function(b){var c;a:{switch(a[0]){case "Tuple2":b:{switch(b[0]){case "Tuple2":var d=function(a){return["Tuple2",b[2],["Tuple2",a,b[2]]]};c=function(){switch(b[1][0]){case "DragFrom":var c;a[1]?c=["Tuple2",uncurry(move)(l(a[2])(b[1][1]))(b[2]),["Tuple2",["DragFrom",
+b[1][1]],b[2]]]:(c=uncurry(move)(l(a[2])(b[1][1]))(b[2]),c=["Tuple2",c,["Tuple2",g,c]]);return c;case "Ignore":return d(a[1]?s:g);case "Listen":return d(not(a[1])?g:isWithin(a[2])(b[2])?["DragFrom",a[2]]:s)}throw"Non-exhaustive pattern match in case";}();break b}break}break a}throw"Non-exhaustive pattern match in case";}return c}}try{if(!(Elm.Prelude instanceof Object))throw"module not found";}catch(h){throw"Module 'Prelude' is missing. Compile with --make flag or load missing module in a separate JavaScript file.";
+}var f={};for(this.i in Elm.Prelude)f[this.i]||eval("var "+this.i+" = Elm.Prelude[this.i];");var g=["Listen"],s=["Ignore"];d[">>>"]=function(a){return function(c){var e;a:{switch(a[0]){case "Automaton":e=a[1];break a}throw"Non-exhaustive pattern match in case";}var f;a:{switch(c[0]){case "Automaton":f=c[1];break a}throw"Non-exhaustive pattern match in case";}return b(function(a){var a=e(a),b;a:{switch(a[0]){case "Tuple2":b=a[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(a[0]){case "Tuple2":a=
+a[2];break a}throw"Non-exhaustive pattern match in case";}var c=f(b);a:{switch(c[0]){case "Tuple2":b=c[1];break a}throw"Non-exhaustive pattern match in case";}a:{switch(c[0]){case "Tuple2":c=c[2];break a}throw"Non-exhaustive pattern match in case";}return["Tuple2",b,d[">>>"](a)(c)]})}};d["<<<"]=function(a){return function(b){return d[">>>"](b)(a)}};d["^>>"]=function(a){return function(b){return d[">>>"](i(a))(b)}};d[">>^"]=function(a){return function(b){return d[">>>"](a)(i(b))}};d["^<<"]=function(a){return function(b){return d[">>>"](b)(i(a))}};
+d["<<^"]=function(a){return function(b){return d[">>>"](i(b))(a)}};f=a(0)(function(){return function(a){return 1+a}});return{$op:{">>>":d[">>>"],"<<<":d["<<<"],"^>>":d["^>>"],">>^":d[">>^"],"^<<":d["^<<"],"<<^":d["<<^"]},run:function(a){return function(b){a:{switch(a[0]){case "Automaton":b=lift(fst)(foldp_(function(a){return function(b){a:{switch(b[0]){case "Tuple2":switch(b[2][0]){case "Automaton":b=b[2][1](a);break a}}throw"Non-exhaustive pattern match in case";}return b}})(a[1])(b));break a}throw"Non-exhaustive pattern match in case";
+}return b}},step:function(a){return function(b){a:{switch(a[0]){case "Automaton":b=a[1](b);break a}throw"Non-exhaustive pattern match in case";}return b}},combine:c,pure:i,init:a,init_:j,count:f,draggable:function(a){return j(["Tuple2",g,a])(n)}}}();Elm.main=function(){return Elm.Automaton.main}}catch(c){Elm.main=function(){document.body.innerHTML=Elm.Text.monospace('<br/><h2>Your browser may not be supported. Are you using a modern browser?</h2><br/><span style="color:grey">Runtime Error in Automaton module:<br/>'+
+c+"</span>");throw c;}}})();
diff --git a/src/Ast.hs b/src/Ast.hs
--- a/src/Ast.hs
+++ b/src/Ast.hs
@@ -3,8 +3,7 @@
 
 import Data.Char (isDigit)
 import Data.List (intercalate)
-import Types
-import Guid
+import Types.Types
 import qualified Text.Pandoc as Pandoc
 
 data Module = Module [String] Exports Imports [Statement]
@@ -30,21 +29,23 @@
           | Lambda String Expr
           | App Expr Expr
           | If Expr Expr Expr
+          | Guard [(Expr,Expr)]
           | Lift Expr [Expr]
           | Fold Expr Expr Expr
           | Async Expr
           | Input String
-          | Let [Definition] Expr
+          | Let [Def] Expr
           | Var String
           | Case Expr [(Pattern,Expr)]
           | Data String [Expr]
           | Markdown Pandoc.Pandoc
             deriving (Eq)
 
-data Definition = Definition String [String] Expr
+data Def = FnDef String [String] Expr
+         | OpDef String String String Expr
                   deriving (Eq)
 
-data Statement = Def String [String] Expr
+data Statement = Definition Def
                | Datatype String [X] [(String,[Type])]
                | ImportEvent String Expr String Type
                | ExportEvent String String Type
@@ -91,6 +92,7 @@
                       concat [ "\\", intercalate " " xs, " -> ", show e' ]
   show (App e1 e2) = show' e1 ++ " " ++ show' e2
   show (If e1 e2 e3) = concat [ "if ", show e1, " then ", show e2, " else ", show e3 ]
+  show (Guard ps) = concatMap (\(b,e) -> concat ["\n  | ",show b," = ",show e]) ps
   show (Let defs e) = "let { " ++ intercalate " ; " (map show defs) ++ " } in " ++ show e
   show (Var x) = x
   show (Case e pats) = "case " ++ show e ++ " of { " ++ intercalate " ; " (map (\(p,e) -> show p ++ " -> " ++ show e) pats) ++ " }"
@@ -105,9 +107,10 @@
   show (Markdown _) = "[markdown| ... |]"
 
 
-instance Show Definition where
-  show (Definition v [] e) = v ++ " = " ++ show e
-  show (Definition f args e) = f ++ " " ++ intercalate " " args ++ " = " ++ show e
+instance Show Def where
+  show (FnDef v [] e) = v ++ " = " ++ show e
+  show (FnDef f args e) = f ++ " " ++ intercalate " " args ++ " = " ++ show e
+  show (OpDef op a1 a2 e) = intercalate " " [a1,op,a2] ++ " = " ++ show e
 
 getLambdas (Lambda x e) = (x:xs,e')
     where (xs,e') = getLambdas e
diff --git a/src/Compiler.hs b/src/Compiler.hs
--- a/src/Compiler.hs
+++ b/src/Compiler.hs
@@ -6,6 +6,7 @@
 import Data.Maybe (fromMaybe)
 import Data.Version (showVersion)
 import System.Console.CmdArgs
+import System.FilePath
 import Text.Blaze.Html.Renderer.String (renderHtml)
 
 import qualified Text.Jasmine as JS
@@ -17,7 +18,6 @@
 import GenerateHtml
 import Paths_Elm
 
-
 data ELM =
     ELM { make :: Bool
         , files :: [FilePath]
@@ -27,6 +27,7 @@
         , import_js :: [FilePath]
         , generate_noscript :: Bool
         , minify :: Bool
+	, output_directory :: Maybe FilePath
         }
     deriving (Data,Typeable,Show,Eq)
 
@@ -39,6 +40,7 @@
           , import_js = [] &= typFile &= help "Include a JavaScript file before the body of the Elm program. Can be used many times. Files will be included in the given order."
           , generate_noscript = True &= help "Add generated <noscript> tag to HTML output."
           , minify = False &= help "Minify generated JavaScript"
+	  , output_directory = Nothing &= typFile &= help "Output files to directory specified. Defaults to the location of original file."
           } &=
     help "Compile Elm programs to HTML, CSS, and JavaScript." &=
     summary ("The Elm Compiler " ++ showVersion version ++ ", (c) Evan Czaplicki")
@@ -48,17 +50,17 @@
   mini <- getDataFileName ("elm-runtime-" ++ showVersion version ++ ".js")
   compileArgs mini args
 
-compileArgs mini (ELM _ [] _ _ _ _ _ _) =
+compileArgs mini (ELM _ [] _ _ _ _ _ _ _) =
     putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
-compileArgs mini (ELM make files rtLoc split only js nscrpt isMini) =
-    mapM_ (fileTo isMini get what js nscrpt $ fromMaybe mini rtLoc) files
+compileArgs mini (ELM make files rtLoc split only js nscrpt isMini outputDir) =
+    mapM_ (fileTo isMini get what js nscrpt outputDir $ fromMaybe mini rtLoc) files
         where get = if make then getModules [] else getModule
               what = if only then JS else
                          if split then Split else HTML
 
 data What = JS | HTML | Split
 
-fileTo isMini get what jsFiles noscript rtLoc file = do
+fileTo isMini get what jsFiles noscript outputDir rtLoc file = do
   let jsStyle = if isMini then Minified else Readable
   let formatJS = if isMini then BS.unpack . JS.minify . BS.pack else id
   ems <- get file
@@ -66,9 +68,9 @@
   case ems of
     Left err -> putStrLn $ "Error while compiling " ++ file ++ ":\n" ++ err
     Right ms ->
-        let name = reverse . tail . dropWhile (/='.') $ reverse file
-            js = name ++ ".js"
-            html = name ++ ".html"
+        let path = fromMaybe "" outputDir </> file
+            js = replaceExtension path ".js"
+            html = replaceExtension path ".html"
         in  case what of
               JS -> writeFile js . formatJS $ jss ++ concatMap jsModule ms
               HTML -> writeFile html . renderHtml $ modulesToHtml jsStyle "" rtLoc jss noscript ms
@@ -101,10 +103,10 @@
 toFilePath modul = map (\c -> if c == '.' then '/' else c) modul ++ ".elm"
 
 builtInModules =
-    concat [ [ "List", "Char", "Maybe", "Dict", "Set", "Automaton" ]
+    concat [ [ "List", "Char", "Maybe", "Dict", "Set", "Automaton", "Date" ]
            , [ "Signal", "Mouse", "Keyboard.Raw"
              , "Window", "Time", "HTTP", "Input", "Random" ]
            , [ "Graphics", "Text", "Color" ]
-           , map ("JavaScript"++) [ "", "Experimental" ]
+           , map ("JavaScript"++) [ "", ".Experimental" ]
            , [ "Prelude", "JSON" ]
            ]
diff --git a/src/Gen/CompileToJS.hs b/src/Gen/CompileToJS.hs
--- a/src/Gen/CompileToJS.hs
+++ b/src/Gen/CompileToJS.hs
@@ -7,16 +7,18 @@
 import Data.Char (isAlpha,isDigit)
 import Data.List (intercalate,sortBy,inits,foldl')
 import Data.Map (toList)
-import Data.Maybe (mapMaybe)
+import Data.Either (partitionEithers)
 import qualified Text.Pandoc as Pan
 
 import Initialize
 import Rename (derename)
 import Cases
 import Guid
+import Parse.Library (isOp)
+import Rename (deprime)
 
 showErr :: String -> String
-showErr err = mainEquals $ "text(monospace(" ++ msg ++ "))"
+showErr err = mainEquals $ "Elm.Graphics.text(Elm.Text.monospace(" ++ msg ++ "))"
     where msg = show . concatMap (++"<br>") . lines $ err
 
 indent = concatMap f
@@ -30,18 +32,25 @@
 assign x e = "\nvar " ++ x ++ "=" ++ e ++ ";"
 ret e = "\nreturn "++ e ++";"
 iff a b c = a ++ "?" ++ b ++ ":" ++ c
+quoted s  = "'" ++ concatMap f s ++ "'"
+    where f '\n' = "\\n"
+          f '\'' = "\\'"
+          f '\t' = "\\t"
+          f '\"' = "\\\""
+          f '\\' = "\\\\"
+          f c    = [c]
 
 mainEquals s = globalAssign "Elm.main" (jsFunc "" (ret s))
 globalAssign m s = "\n" ++ m ++ "=" ++ s ++ ";"
 
 tryBlock escapees names e = 
     concat [ "\ntry{\n" ++ e ++ "\n} catch (e) {"
-           , "Elm.main=function() {"
-	   , "var msg = ('<br/><h2>Your browser may not be supported. " ++
+           , "\nElm.main=function() {"
+	   , "\nvar msg = ('<br/><h2>Your browser may not be supported. " ++
              "Are you using a modern browser?</h2>' +" ++
              " '<br/><span style=\"color:grey\">Runtime Error in " ++
              intercalate "." names ++ " module:<br/>' + e + '" ++ msg ++ "</span>');"
-	   , "document.body.innerHTML = Text.monospace(msg);"
+	   , "\ndocument.body.innerHTML = Elm.Text.monospace(msg);"
            , "throw e;"
            , "};}"
            ]
@@ -55,13 +64,12 @@
 
 jsModule (escapees, Module names exports imports stmts) =
     tryBlock escapees (tail modNames) $ concat
-           [ "\nfor(var i in Elm) { this[i] = Elm[i]; }"
-           , concatMap (\n -> globalAssign n $ n ++ " || {}") .
+           [ concatMap (\n -> globalAssign n $ n ++ " || {}") .
              map (intercalate ".") . drop 2 . inits $
              take (length modNames - 1) modNames
            , "\nif (" ++ modName ++ ") throw \"Module name collision, '" ++
              intercalate "." (tail modNames) ++ "' is already defined.\"; "
-           , globalAssign modName $ jsFunc "" (includes ++body++ export) ++ "()"
+           , globalAssign modName $ jsFunc "" (defs ++ includes ++ body ++ export) ++ "()"
            , mainEquals $ modName ++ ".main" ]
         where modNames = if null names then ["Elm", "Main"]
                                        else  "Elm" : names
@@ -70,87 +78,118 @@
               body = stmtsToJS stmts
               export = getExports exports stmts
               exps = if null exports then ["main"] else exports
+              defs = concat [ assign "$op" "{}"
+                            , "\nfor(Elm['i'] in Elm){eval('var '+Elm['i']+'=Elm[Elm.i];');}" ]
 
-getExports names stmts = ret . braces $ intercalate "," pairs
-    where pairs = mapMaybe pair $ concatMap get stmts
-          pair x = if null names || y `elem` names then
-                       Just $ y ++ ":" ++ x else Nothing
-              where y = derename x
-          get s = case s of Def x _ _           -> [x]
-                            Datatype _ _ tcs    -> map fst tcs
-                            ImportEvent _ _ x _ -> [x]
+getExports names stmts = ret . braces $ intercalate ",\n" (op : map fnPair fns)
+    where exNames n = either derename id n `elem` names
+          exports | null names = concatMap get stmts
+                  | otherwise  = filter exNames (concatMap get stmts)
+
+          (fns,ops) = partitionEithers exports
+
+          opPair op = "'" ++ op ++ "' : $op['" ++ op ++ "']"
+          fnPair fn = let fn' = derename fn in fn' ++ ":" ++ fn
+
+          op = ("$op : "++) . braces . intercalate ", " $ map opPair ops
+
+          get' (FnDef x _ _) = Left x
+          get' (OpDef op _ _ _) = Right op
+          get s = case s of Definition d        -> [ get' d ]
+                            Datatype _ _ tcs    -> map (Left . fst) tcs
+                            ImportEvent _ _ x _ -> [ Left x ]
                             ExportEvent _ _ _   -> []
 
 
 jsImport (modul, how) =
-  concat [ "\ntry{if (!(" ++ modul ++ " instanceof Object)) throw 'module not found'; } catch(e) {throw \"Module '"
+  concat [ "\ntry{\n if (!(" ++ modul ++ " instanceof Object)) throw 'module not found';\n} catch(e) {\n throw (\"Module '"
          , drop 1 (dropWhile (/='.') modul)
          , "' is missing. Compile with --make flag or load missing "
-         , "module in a separate JavaScript file.\";}" ] ++
+         , "module in a separate JavaScript file.\");\n}" ] ++
      jsImport' (modul, how)
   
 jsImport' (modul, As name) = assign name modul
-jsImport' (modul, Importing vs) =
-    concatMap (\v -> assign v $ modul ++ "." ++ v) vs
+jsImport' (modul, Importing vs) = concatMap def vs
+    where def [] = []
+          def (o:p) | isOp o    = let v = "$op['" ++ o:p ++ "']" in
+                                  "\n" ++ v ++ " = " ++ modul ++ "." ++ v ++ ";"
+                    | otherwise = let v = deprime (o:p) in
+                                  assign v $ modul ++ "." ++ v
+
 jsImport' (modul, Hiding vs) =
-    concat [ assign "hiddenVars" . jsList $ map (\v -> "'" ++ v ++ "'") vs
-           , "\nfor(var i in " ++ modul ++ "){"
-           , indent $ "\nif (hiddenVars.indexOf(i) >= 0) continue;"
-           , indent $ globalAssign "this[i]" $ modul ++ "[i]"
-           , "}" ]
+    concat [ assign "hiddenVars" . ("{"++) . (++"}") . intercalate "," $
+                    map (\v -> v ++ ":true") (map deprime vs)
+           , "\nfor (Elm['i'] in " ++ modul ++ ") "
+           , braces . indent . concat $
+               [ "\nif (hiddenVars[Elm['i']]) continue;"
+               , "\neval('var ' + Elm['i'] + ' = "
+               , modul, "[Elm.i];');" ]
+           ]
 
 stmtsToJS :: [Statement] -> String
-stmtsToJS stmts = concatMap stmtToJS (sortBy cmpStmt stmts)
+stmtsToJS stmts = run (concat `liftM` mapM toJS (sortBy cmpStmt stmts))
     where cmpStmt s1 s2 = compare (valueOf s1) (valueOf s2)
-          valueOf s = case s of Datatype _ _ _      -> 1
-                                ImportEvent _ _ _ _ -> 3
-                                Def _ [] _          -> 3
-                                Def _ _ _           -> 4
-                                ExportEvent _ _ _   -> 5
+          valueOf s = case s of
+                        Datatype _ _ _             -> 1
+                        ImportEvent _ _ _ _        -> 2
+                        Definition (FnDef f [] _)  ->
+                            if derename f == "main" then 5 else 4
+                        Definition _               -> 3
+                        ExportEvent _ _ _          -> 6
 
-stmtToJS :: Statement -> String
-stmtToJS (Def name [] e) = assign name (toJS e)
-stmtToJS (Def name (a:as) e) = "\nfunction " ++ name ++ parens a ++
-                               braces (indent . ret . toJS $ foldr Lambda e as) ++ ";"
-stmtToJS (Datatype _ _ tcs) = concatMap (stmtToJS . toDef) tcs
-    where toDef (name,args) = Def name vars $ Data (derename name) (map Var vars)
-              where vars = map (('a':) . show) [1..length args]
-stmtToJS (ImportEvent js base elm _) =
-    concat [ "\nvar " ++ elm ++ " = Elm.Signal.constant(" ++ toJS base ++ ");"
-           , "\nValue.addListener(document, '" ++ js
-           , "', function(e) { Dispatcher.notify(" ++ elm
-           , ".id, e.value); });" ]
-stmtToJS (ExportEvent js elm _) =
-    concat [ "\nlift(function(v) { var e = document.createEvent('Event');"
-           , "e.initEvent('" ++ js ++ "', true, true);"
-           , "e.value = v;"
-           , "document.dispatchEvent(e); return v; })(" ++ elm ++ ");"
-           ]
+class ToJS a where
+  toJS :: a -> GuidCounter String
 
+instance ToJS Def where
+  toJS (FnDef x [] e) = assign x `liftM` toJS e
+  toJS (FnDef f (a:as) e) =
+      do body <- toJS (foldr Lambda e as)
+         return $ concat ["\nfunction ",f,parens a, braces . indent $ ret body]
+  toJS (OpDef op a1 a2 e) =
+      do body <- toJS (foldr Lambda e [a1,a2])
+         return $ concat [ "\n$op['", op, "'] = ", body, ";" ]
 
-toJS = run . toJS'
+instance ToJS Statement where
+    toJS (Definition d) = toJS d
+    toJS (Datatype _ _ tcs) = concat `liftM` mapM (toJS . toDef) tcs
+        where toDef (name,args) =
+                  Definition . FnDef name vars $ Data (derename name) (map Var vars)
+                      where vars = map (('a':) . show) [1..length args]
+    toJS (ImportEvent js base elm _) =
+        do v <- toJS base
+           return $ concat [ "\nvar " ++ elm ++ "=Elm.Signal.constant(" ++ v ++ ");"
+                           , "\nValue.addListener(document, '" ++ js
+                           , "', function(e) { Dispatcher.notify(" ++ elm
+                           , ".id, e.value); });" ]
+    toJS (ExportEvent js elm _) =
+        return $ concat [ "\nlift(function(v) { "
+                        , "var e = document.createEvent('Event');"
+                        , "e.initEvent('", js, "', true, true);"
+                        , "e.value = v;"
+                        , "document.dispatchEvent(e); return v; })(", elm, ");" ]
 
-toJS' :: Expr -> GuidCounter String
-toJS' expr =
+instance ToJS Expr where
+  toJS expr =
     case expr of
       IntNum n -> return $ show n
       FloatNum n -> return $ show n
       Var x -> return $ x
-      Chr c -> return $ show c
-      Str s -> return $ "Value.str" ++ parens (show s)
+      Chr c -> return $ quoted [c]
+      Str s -> return $ "Value.str" ++ parens (quoted s)
       Boolean b -> return $ if b then "true" else "false"
-      Range lo hi -> jsRange `liftM` toJS' lo `ap` toJS' hi
-      Access e lbl -> (\s -> s ++ "." ++ lbl) `liftM` toJS' e
-      Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
-      If eb et ef -> parens `liftM` (iff `liftM` toJS' eb `ap` toJS' et `ap` toJS' ef)
-      Lambda v e -> liftM (jsFunc v . ret) (toJS' e)
-      App (Var "toText") (Str s) -> return $ "toText" ++ parens (show s)
-      App (Var "link") (Str s) -> return $ "link(" ++ show s ++ ")"
-      App (Var "plainText") (Str s) -> return $ "plainText(" ++ show s ++ ")"
-      App e1 e2 -> (++) `liftM` (toJS' e1) `ap` (parens `liftM` toJS' e2)
+      Range lo hi -> jsRange `liftM` toJS lo `ap` toJS hi
+      Access e lbl -> (\s -> s ++ "." ++ lbl) `liftM` toJS e
+      Binop op e1 e2 -> binop op `liftM` toJS e1 `ap` toJS e2
+      If eb et ef -> parens `liftM` (iff `liftM` toJS eb `ap` toJS et `ap` toJS ef)
+      Guard ps -> guardToJS ps
+      Lambda v e -> liftM (jsFunc v . ret) (toJS e)
+      App (Var "toText") (Str s) -> return $ "toText" ++ parens (quoted s)
+      App (Var "link") (Str s) -> return $ "link(" ++ quoted s ++ ")"
+      App (Var "plainText") (Str s) -> return $ "plainText(" ++ quoted s ++ ")"
+      App e1 e2 -> (++) `liftM` (toJS e1) `ap` (parens `liftM` toJS e2)
       Let defs e -> jsLet defs e
       Case e cases -> caseToJS e cases
-      Data name es -> (\ss -> jsList $ show name : ss) `liftM` mapM toJS' es
+      Data name es -> (\ss -> jsList $ quoted name : ss) `liftM` mapM toJS es
       Markdown doc -> return $ "text('" ++ pad ++ md ++ pad ++ "')"
           where md = formatMarkdown $ Pan.writeHtmlString Pan.defaultWriterOptions doc
                 pad = "<div style=\"height:0;width:0;\">&nbsp;</div>"
@@ -161,21 +200,25 @@
           f '"'  = "\""
           f c = [c]
 
+guardToJS ps = format `liftM` mapM f ps
+    where format cs = foldr (\c e -> parens $ c ++ " : " ++ e) err cs
+          err = "(function(){throw \"Non-exhaustive guard expression\";}())"
+          f (b,e) = do b' <- toJS b
+                       e' <- toJS e
+                       return (b' ++ " ? " ++ e')
+
 jsLet defs e' = do
-  body <- (++) `liftM` jsDefs defs `ap` (ret `liftM` toJS' e')
+  body <- (++) `liftM` jsDefs defs `ap` (ret `liftM` toJS e')
   return $ jsFunc "" body ++ "()"
 
-jsDefs defs = concat `liftM` mapM toDef (sortBy f defs)
+jsDefs defs = concat `liftM` mapM toJS (sortBy f defs)
     where f a b = compare (valueOf a) (valueOf b)
-          valueOf (Definition _ args _) = min 1 (length args)
-          toDef (Definition x [] e) = assign x `liftM` toJS' e
-          toDef (Definition f (a:as) e) = do
-            out <- toJS' $ foldr Lambda e as
-            return $ "\nfunction " ++ f ++ parens a ++ braces (indent $ ret out) ++ ";"
+          valueOf (FnDef _ args _) = min 1 (length args)
+          valueOf (OpDef _ _ _ _)  = 1
 
 caseToJS e ps = do
   match <- caseToMatch ps
-  e' <- toJS' e
+  e' <- toJS e
   (match',stmt) <- case (match,e) of
                      (Match name _ _, Var x) -> return (matchSubst [(name,x)] match, "")
                      (Match name _ _, _    ) -> return (match, assign name e')
@@ -189,37 +232,41 @@
   return $ concat [ "\nswitch(", name, "[0]){", indent cases, "\n}", finally ]
 matchToJS Fail  = return "\nthrow \"Non-exhaustive pattern match in case\";"
 matchToJS Break = return "break;"
-matchToJS (Other e) = ret `liftM` toJS' e
+matchToJS (Other e) = ret `liftM` toJS e
 matchToJS (Seq ms) = concat `liftM` mapM matchToJS ms
 
 clauseToJS var (Clause name vars e) = do
   let vars' = map (\n -> var ++ "[" ++ show n ++ "]") [ 1 .. length vars ]
   s <- matchToJS $ matchSubst (zip vars vars') e
-  return $ concat [ "\ncase ", show name, ":", s ]
+  return $ concat [ "\ncase ", quoted name, ":", s ]
 
 jsNil         = "[\"Nil\"]"
-jsCons  e1 e2 = jsList [ show "Cons", e1, e2 ]
+jsCons  e1 e2 = jsList [ quoted "Cons", e1, e2 ]
 jsRange e1 e2 = (++"()") . jsFunc "" $
                 assign "lo" e1 ++ assign "hi" e2 ++ assign "lst" jsNil ++
-                "if(lo<=hi){do{" ++ assign "lst" (jsCons "hi" "lst") ++ "}while(hi-->lo)}" ++
+                "if(lo<=hi){do{lst=" ++ (jsCons "hi" "lst") ++ "}while(hi-->lo)}" ++
                 ret "lst"
 
 binop (o:p) e1 e2
     | isAlpha o || '_' == o = (o:p) ++ parens e1 ++ parens e2
-    | otherwise = case o:p of
-                    ":"  -> jsCons e1 e2
-                    "++" -> append e1 e2
-                    "$"  -> e1 ++ parens e2
-                    "."  -> jsFunc "x" . ret $ e1 ++ parens (e2 ++ parens "x")
-                    "^"  -> "Math.pow(" ++ e1 ++ "," ++ e2 ++ ")"
-                    "==" -> "eq(" ++ e1 ++ "," ++ e2 ++ ")"
-                    "/=" -> "not(eq(" ++ e1 ++ "," ++ e2 ++ "))"
-                    "<"  -> "(compare(" ++ e1 ++ ")(" ++ e2 ++ ")[0] === 'LT')"
-                    ">"  -> "(compare(" ++ e1 ++ ")(" ++ e2 ++ ")[0] === 'GT')"
-                    "<=" -> "function() { var ord = compare(" ++ e1 ++ ")(" ++ e2 ++ ")[0]; return ord === 'LT' || ord === 'EQ'; }()"
-                    ">=" -> "function() { var ord = compare(" ++ e1 ++ ")(" ++ e2 ++ ")[0]; return ord === 'GT' || ord === 'EQ'; }()"
-                    ">>>" -> "composeAuto(" ++ e1 ++ ")(" ++ e2 ++ ")"
-                    "<<<" -> "composeAuto(" ++ e2 ++ ")(" ++ e1 ++ ")"
-                    _    -> parens (e1 ++ (o:p) ++ e2)
+    | otherwise =
+        let ops = ["+","-","*","/","&&","||"] in
+        case o:p of
+          ":"  -> jsCons e1 e2
+          "++" -> append e1 e2
+          "$"  -> e1 ++ parens e2
+          "."  -> jsFunc "x" . ret $ e1 ++ parens (e2 ++ parens "x")
+          "^"  -> "Math.pow(" ++ e1 ++ "," ++ e2 ++ ")"
+          "==" -> "eq(" ++ e1 ++ "," ++ e2 ++ ")"
+          "/=" -> "not(eq(" ++ e1 ++ "," ++ e2 ++ "))"
+          "<"  -> "(compare(" ++ e1 ++ ")(" ++ e2 ++ ")[0] === 'LT')"
+          ">"  -> "(compare(" ++ e1 ++ ")(" ++ e2 ++ ")[0] === 'GT')"
+          "<=" -> "function() { var ord = compare(" ++ e1 ++ ")(" ++
+                  e2 ++ ")[0]; return ord==='LT' || ord==='EQ'; }()"
+          ">=" -> "function() { var ord = compare(" ++ e1 ++ ")(" ++
+                  e2 ++ ")[0]; return ord==='GT' || ord==='EQ'; }()"
+          _  | elem (o:p) ops -> parens (e1 ++ (o:p) ++ e2)
+             | otherwise      -> concat [ "$op['", o:p, "']"
+                                        , parens e1, parens e2 ]
 
 append e1 e2 = "Value.append" ++ parens (e1 ++ "," ++ e2)
diff --git a/src/Gen/ExtractNoscript.hs b/src/Gen/ExtractNoscript.hs
--- a/src/Gen/ExtractNoscript.hs
+++ b/src/Gen/ExtractNoscript.hs
@@ -1,37 +1,56 @@
 
-module ExtractNoscript (extract) where
+module ExtractNoscript (extractNoscript) where
 
 import Ast
 import qualified Text.Pandoc as Pan
 
-extract (Module _ _ _ stmts) =
-    concatMap (\s -> "<p>" ++ s ++ "</p>") (concatMap stmtExtract stmts)
-        where stmtExtract (Def _ _ e) = extract' e
-              stmtExtract _ = []
+extractNoscript :: Module -> String
+extractNoscript modul = concat (extract modul)
 
-extract' expr =
-    let f = extract' in
+class Extract a where
+  extract :: a -> [String]
+
+instance Extract Module where
+  extract (Module _ _ _ stmts) =
+      map (\s -> "<p>" ++ s ++ "</p>") (concatMap extract stmts)
+
+instance Extract Statement where
+  extract (Definition d) = extract d
+  extract _ = []
+
+instance Extract Def where
+  extract (FnDef _ _ e)   = extract e
+  extract (OpDef _ _ _ e) = extract e
+
+instance Extract Expr where
+  extract expr =
+    let f = extract in
     case expr of
       Str s -> [s]
       Binop op e1 e2 -> case (op, f e1, f e2) of
                           ("++", [s1], [s2]) -> [s1 ++ s2]
                           (_   , ss1 , ss2 ) -> ss1 ++ ss2
       Lambda v e -> f e
-      App (App (Var "link") src) txt ->
-          case (f src, f txt) of
-            ([s1],[s2]) -> [ "<a href=\"" ++ s1 ++ "\">" ++ s2 ++ "</a>" ]
-            ( ss1, ss2) -> ss1 ++ ss2
+      App (App (Var "link") src) txt -> linkExtract src txt
+      App (App (Var "Graphics.link") src) txt -> linkExtract src txt
+      App (App (Var "Text.link") src) txt -> linkExtract src txt
       App (Var "header") e -> tag "h1" e
       App (Var "bold") e -> tag "b" e
       App (Var "italic") e -> tag "i" e
       App (Var "monospace") e -> tag "code" e
       App e1 e2 -> f e1 ++ f e2
       If eb et ef -> f et ++ f ef
-      Let defs e -> concatMap (\(Definition _ _ d) -> f d) defs ++ f e
+      Let defs e -> concatMap extract defs ++ f e
       Var _ -> []
       Case e cases -> concatMap (f . snd) cases
       Data _ es -> concatMap f es
       Markdown doc -> [ Pan.writeHtmlString Pan.defaultWriterOptions doc ]
       _ -> []
 
-tag t e = map (\s -> concat [ "<", t, ">", s, "</", t, ">" ]) (extract' e)
+linkExtract src txt =
+    case (extract src, extract txt) of
+      ([s1],[s2]) -> [ "<a href=\"" ++ s1 ++ "\">" ++ s2 ++ "</a>" ]
+      ( ss1, ss2) -> ss1 ++ ss2
+
+
+tag t e = map (\s -> concat [ "<", t, ">", s, "</", t, ">" ]) (extract e)
diff --git a/src/Gen/GenerateHtml.hs b/src/Gen/GenerateHtml.hs
--- a/src/Gen/GenerateHtml.hs
+++ b/src/Gen/GenerateHtml.hs
@@ -29,7 +29,8 @@
 makeScript :: JSStyle -> Either String String -> H.Html
 makeScript _ (Left s) =
     H.script ! A.type_ "text/javascript" ! A.src (H.toValue s) $ ""
-makeScript jsStyle (Right s) = H.script ! A.type_ "text/javascript" $ preEscapedToMarkup content
+makeScript jsStyle (Right s) =
+    H.script ! A.type_ "text/javascript" $ preEscapedToMarkup content
     where content = case jsStyle of 
                       Minified -> BS.unpack . minify . BS.pack $ s
                       Readable -> s
@@ -49,10 +50,11 @@
       Right (escs, modul) -> modulesToHtml Readable title libLoc [] True [(escs,modul)]
 
 
-modulesToHtml jsStyle title libLoc jss nscrpt pairs = createHtml jsStyle libLoc title' js noscript
+modulesToHtml jsStyle title libLoc jss nscrpt pairs =
+    createHtml jsStyle libLoc title' js noscript
     where modules = map snd pairs
           js = Right $ jss ++ concatMap jsModule pairs
-          noscript = if nscrpt then extract $ last modules else ""
+          noscript = if nscrpt then extractNoscript $ last modules else ""
           title' = if null title then altTitle else title
           altTitle = (\(Module names _ _ _) -> intercalate "." names) $
                      last modules
diff --git a/src/Initialize.hs b/src/Initialize.hs
--- a/src/Initialize.hs
+++ b/src/Initialize.hs
@@ -5,19 +5,18 @@
 import Data.List (lookup)
 
 import Ast
-import Parser (parseProgram)
+import Parse.Parser (parseProgram)
 import Rename
-import Types ((-:))
+import Types.Types ((-:))
 import Types.Hints (hints)
 import Types.Unify
 import Optimize
 
 
 initialize str =
-    let nameOf (Definition n _ _) = n in
     do modul@(Module name ex im stmts) <- parseProgram str
        (escapees, subs) <- unify hints modul
-       let modul' = optimize . rename $ Module name ex im' stmts
+       let modul' = optimize . renameModule $ Module name ex im' stmts
                where im' | any ((=="Prelude") . fst) im = im
-                         | otherwise = ("Prelude", Importing []) : im
+                         | otherwise = ("Prelude", Hiding []) : im
        subs `seq` return (escapees, modul')
diff --git a/src/Language/Elm.hs b/src/Language/Elm.hs
--- a/src/Language/Elm.hs
+++ b/src/Language/Elm.hs
@@ -79,4 +79,4 @@
 toPartsHelper source = (html, css, js)
   where modul = initialize source
         js = either showErr jsModule modul
-        html = widgetBody $ either id (extract . snd) modul
+        html = widgetBody $ either id (extractNoscript . snd) modul
diff --git a/src/Optimize.hs b/src/Optimize.hs
--- a/src/Optimize.hs
+++ b/src/Optimize.hs
@@ -9,13 +9,23 @@
     Module name ims exs (map optimizeStmt stmts)
 
 optimizeStmt stmt = if stmt == stmt' then stmt' else optimizeStmt stmt'
-    where stmt' = simpStmt stmt
-          simpStmt (Def name args e) = Def name args (simp e)
-          simpStmt (ImportEvent js b elm t) = ImportEvent js (simp b) elm t
-          simpStmt stmt = stmt
+    where stmt' = simp stmt
 
-simp :: Expr -> Expr
-simp expr =
+class Simplify a where
+  simp :: a -> a
+
+instance Simplify Statement where
+  simp (Definition def) = Definition (simp def)
+  simp (ImportEvent js b elm t) = ImportEvent js (simp b) elm t
+  simp stmt = stmt
+
+instance Simplify Def where
+  simp (FnDef func args e) = FnDef func args (simp e)
+  simp (OpDef op a1 a2 e)  = OpDef op a1 a2 (simp e)
+  
+
+instance Simplify Expr where
+  simp expr =
     let f = simp in
     case expr of
       Range e1 e2 -> Range (f e1) (f e2)
@@ -26,8 +36,7 @@
               where { e1' = f e1 ; e2' = f e2 }
       App e1 e2 -> App (f e1) (f e2)
       If e1 e2 e3 -> simp_if (f e1) (f e2) (f e3)
-      Let defs e -> Let (map simpDef defs) (f e)
-              where simpDef (Definition func args e) = Definition func args (f e)
+      Let defs e -> Let (map simp defs) (f e)
       Data name es -> Data name (map f es)
       Case e cases -> Case (f e) (map (second f) cases)
       _ -> expr
diff --git a/src/Parse/Binops.hs b/src/Parse/Binops.hs
--- a/src/Parse/Binops.hs
+++ b/src/Parse/Binops.hs
@@ -1,4 +1,4 @@
-module Binops (binops) where
+module Parse.Binops (binops) where
 
 import Ast
 import Control.Monad (liftM,guard)
@@ -8,7 +8,7 @@
 import Data.Maybe (mapMaybe)
 
 import Text.Parsec
-import ParseLib
+import Parse.Library
 
 data Assoc = L | N | R deriving (Eq,Show)
 
diff --git a/src/Parse/Expr.hs b/src/Parse/Expr.hs
new file mode 100644
--- /dev/null
+++ b/src/Parse/Expr.hs
@@ -0,0 +1,166 @@
+module Parse.Expr (def,term) where
+
+import Ast
+import Control.Applicative ((<$>), (<*>))
+import Control.Monad
+import Data.Char (isSymbol, isDigit)
+import Data.List (foldl')
+import Text.Parsec hiding (newline,spaces)
+import Text.Parsec.Indent
+import qualified Text.Pandoc as Pan
+
+import Parse.Library
+import Parse.Patterns
+import Parse.Binops
+
+import Guid
+import Types.Types (Type (VarT), Scheme (Forall))
+
+import System.IO.Unsafe
+
+
+--------  Basic Terms  --------
+
+numTerm :: IParser Expr
+numTerm = toExpr <$> (preNum <?> "number")
+    where toExpr n | '.' `elem` n = FloatNum (read n)
+                   | otherwise = IntNum (read n)
+          preNum  = (++) <$> many1 digit <*> option "" postNum
+          postNum = do try $ lookAhead (string "." >> digit)
+                       string "."
+                       ('.':) <$> many1 digit
+
+strTerm :: IParser Expr
+strTerm = liftM Str . expecting "string" . betwixt '"' '"' . many $
+          backslashed <|> satisfy (/='"')
+
+varTerm :: IParser Expr
+varTerm = toVar <$> var <?> "variable"
+
+toVar v = case v of "True"  -> Boolean True
+                    "False" -> Boolean False
+                    _       -> Var v
+
+chrTerm :: IParser Expr
+chrTerm = Chr <$> betwixt '\'' '\'' (backslashed <|> satisfy (/='\''))
+          <?> "character"
+
+
+--------  Complex Terms  --------
+
+listTerm :: IParser Expr
+listTerm = (do { try $ string "[markdown|"
+               ; md <- filter (/='\r') <$> manyTill anyChar (try $ string "|]")
+               ; return . Markdown $ Pan.readMarkdown Pan.defaultParserState md })
+           <|> (braces $ choice
+                [ try $ do { lo <- expr; whitespace; string ".." ; whitespace
+                           ; Range lo <$> expr }
+                , list <$> commaSep expr ])
+
+parensTerm :: IParser Expr
+parensTerm = parens $ choice
+             [ do op <- anyOp
+                  return . Lambda "x" . Lambda "y" $ Binop op (Var "x") (Var "y")
+             , do let comma = char ',' <?> "comma ','"
+                  commas <- comma >> many (whitespace >> comma)
+                  let vars = map (('v':) . show) [ 0 .. length commas + 1 ]
+                  return $ foldr Lambda (tuple $ map Var vars) (vars)
+             , do es <- commaSep expr
+                  return $ case es of { [e] -> e; _ -> tuple es }
+             ]
+
+term :: IParser Expr
+term = choice [ numTerm, strTerm, chrTerm
+              , accessible varTerm
+              , listTerm, parensTerm ]
+       <?> "basic term (4, x, 'c', etc.)"
+
+--------  Applications  --------
+
+appExpr :: IParser Expr
+appExpr = do
+  tlist <- spaceSep1 term
+  return $ case tlist of
+             t:[] -> t
+             t:ts -> foldl' App t ts
+
+--------  Normal Expressions  --------
+
+binaryExpr :: IParser Expr
+binaryExpr = binops appExpr anyOp
+
+ifExpr :: IParser Expr
+ifExpr = do reserved "if"   ; whitespace ; e1 <- expr ; whitespace
+            reserved "then" ; whitespace ; e2 <- expr ; (whitespace <?> "an 'else' branch")
+            reserved "else" <?> "an 'else' branch" ; whitespace ; If e1 e2 <$> expr
+
+lambdaExpr :: IParser Expr
+lambdaExpr = do char '\\' <|> char '\x03BB' <?> "anonymous function"
+                whitespace
+                pats <- spaceSep1 patternTerm
+                whitespace ; arrow ; whitespace
+                e <- expr
+                return $ makeLambda pats e
+
+defSet :: IParser [Def]
+defSet = do
+  brace <- optionMaybe $ do
+             string "{" <?> "a set of definitions { x = ... ; y = ... }"
+             whitespace >> return "{"
+  case brace of
+    Nothing  -> concat <$> block (do d <- assignExpr ; whitespace ; return d)
+    Just "{" -> do dss <- semiSep1 assignExpr
+                   whitespace
+                   string "}" <?> "closing bracket '}'"
+                   return (concat dss)
+
+letExpr :: IParser Expr
+letExpr = do
+  reserved "let" ; whitespace
+  defs <- defSet
+  whitespace ; reserved "in" ; whitespace
+  Let defs <$> expr
+
+caseExpr :: IParser Expr
+caseExpr = do
+  reserved "case"; whitespace; e <- expr; whitespace; reserved "of"; whitespace
+  Case e <$> (with <|> without)
+    where case_ = do p <- patternExpr; whitespace; arrow; whitespace
+                     (,) p <$> expr
+          with    = brackets (semiSep1 (case_ <?> "cases { x -> ... }"))
+          without = block (do c <- case_ ; whitespace ; return c)
+
+expr = choice [ ifExpr, letExpr, caseExpr
+              , lambdaExpr, binaryExpr ] <?> "an expression"
+
+funcDef = try (do p1 <- try patternTerm ; infics p1 <|> func p1)
+          <|> ((:[]) <$> patternExpr)
+          <?> "the definition of a variable (x = ...)"
+    where func p@(PVar v) = (p:) <$> spacePrefix patternTerm
+          func p          = do try (lookAhead (whitespace >> string "="))
+                               return [p]
+          infics p1 = do
+            o:p <- try (whitespace >> anyOp)
+            p2  <- (whitespace >> patternTerm)
+            return $ if o == '`' then [ PVar $ takeWhile (/='`') p, p1, p2 ]
+                                 else [ PVar (o:p), p1, p2 ]
+
+assignExpr :: IParser [Def]
+assignExpr = withPos $ do
+  fDefs <- funcDef
+  whitespace
+  e <- (string "=" >> whitespace >> expr) <|> guardExpr
+  flattenPatterns fDefs e
+
+guardExpr = (Guard <$> spaceSep1 gExpr)
+    where gExpr = do string "|" ; whitespace
+                     b <- expr ; whitespace ; string "=" ; whitespace
+                     (,) b <$> expr
+
+def = map Definition <$> assignExpr
+
+
+parseDef str =
+    case iParse def "" str of
+      Right result -> Right result
+      Left err -> Left $ "Parse error at " ++ show err
diff --git a/src/Parse/Foreign.hs b/src/Parse/Foreign.hs
new file mode 100644
--- /dev/null
+++ b/src/Parse/Foreign.hs
@@ -0,0 +1,61 @@
+
+module Parse.Foreign (foreignDef) where
+
+import Control.Applicative ((<$>), (<*>))
+import Data.Either (partitionEithers)
+import Text.Parsec hiding (newline,spaces)
+
+import Ast
+import Parse.Library
+import Parse.Expr (term)
+import Parse.Types
+import Types.Types (signalOf)
+
+
+foreignDef = do try (reserved "foreign") ; whitespace
+                importEvent <|> exportEvent
+
+exportEvent = do
+  try (reserved "export" >> whitespace >> reserved "jsevent" >> whitespace)
+  js   <- jsVar    ; whitespace
+  elm  <- lowVar   ; whitespace
+  string "::"      ; whitespace
+  tipe <- typeExpr
+  case tipe of
+    ADTPT "Signal" [pt] ->
+        either fail (return . ExportEvent js elm . signalOf) (toForeignType pt)
+    _ -> fail "When exporting events, the exported value must be a Signal."
+
+importEvent = do
+  try (reserved "import" >> whitespace >> reserved "jsevent" >> whitespace)
+  js   <- jsVar ; whitespace
+  base <- term <?> "Base case for imported signal (signals cannot be undefined)"
+  whitespace
+  elm  <- lowVar <?> "Name of imported signal"
+  whitespace ; string "::" ; whitespace
+  tipe <- typeExpr
+  case tipe of
+    ADTPT "Signal" [pt] ->
+        either fail (return . ImportEvent js base elm . signalOf) (toForeignType pt)
+    _ -> fail "When importing events, the imported value must be a Signal."
+
+
+jsVar :: (Monad m) => ParsecT [Char] u m String
+jsVar = betwixt '"' '"' $ do
+  v <- (:) <$> (letter <|> char '_') <*> many (alphaNum <|> char '_')
+  if v `notElem` jsReserveds then return v else
+      fail $ "'" ++ v ++
+          "' is not a good name for a importing or exporting JS values."
+
+jsReserveds =
+    [ "null", "undefined", "Nan", "Infinity", "true", "false", "eval"
+    , "arguments", "int", "byte", "char", "goto", "long", "final", "float"
+    , "short", "double", "native", "throws", "boolean", "abstract", "volatile"
+    , "transient", "synchronized", "function", "break", "case", "catch"
+    , "continue", "debugger", "default", "delete", "do", "else", "finally"
+    , "for", "function", "if", "in", "instanceof", "new", "return", "switch"
+    , "this", "throw", "try", "typeof", "var", "void", "while", "with", "class"
+    , "const", "enum", "export", "extends", "import", "super", "implements"
+    , "interface", "let", "package", "private", "protected", "public"
+    , "static", "yield"
+    ]
diff --git a/src/Parse/Library.hs b/src/Parse/Library.hs
new file mode 100644
--- /dev/null
+++ b/src/Parse/Library.hs
@@ -0,0 +1,158 @@
+
+module Parse.Library where
+
+import Ast
+import Control.Applicative ((<$>),(<*>))
+import Control.Monad
+import Control.Monad.State
+import Data.Char (isSymbol)
+import Text.Parsec hiding (newline,spaces,State)
+import Text.Parsec.Indent
+
+reserveds = [ "if", "then", "else"
+            , "case", "of", "data"
+            , "let", "in"
+            , "module", "where"
+            , "import", "as", "hiding"
+            , "export", "foreign" ]
+
+expecting = flip (<?>)
+
+type IParser a = ParsecT String () (State SourcePos) a
+
+iParse :: IParser a -> SourceName -> String -> Either ParseError a
+iParse aParser source_name input =
+  runIndent source_name $ runParserT aParser () source_name input
+
+backslashed :: IParser Char
+backslashed = do { char '\\'; c <- anyChar
+                 ; return . read $ ['\'','\\',c,'\''] }
+
+var :: IParser String
+var = makeVar (letter <|> char '_' <?> "variable")
+
+lowVar :: IParser String
+lowVar = makeVar (lower <?> "lower case variable")
+capVar :: IParser String
+capVar = makeVar (upper <?> "upper case variable")
+
+innerVarChar :: IParser Char
+innerVarChar = alphaNum <|> char '_' <|> char '\'' <?> "" 
+
+makeVar :: IParser Char -> IParser String
+makeVar p = do v <- (:) <$> p <*> many innerVarChar
+               guard (v `notElem` reserveds)
+               return v
+
+reserved :: String -> IParser String
+reserved word =
+  try (string word >> notFollowedBy innerVarChar) >> return word
+  <?> "reserved word '" ++ word ++ "'"
+
+anyOp :: IParser String
+anyOp = betwixt '`' '`' var <|> symOp <?> "infix operator (e.g. +, *, ||)"
+
+isOp c = isSymbol c || elem c "+-/*=.$<>:&|^?%#@~!"
+
+symOp :: IParser String
+symOp = do op <- many1 (satisfy isOp)
+           guard (op `notElem` [ "=", "..", "->", "--", "|", "\8594" ])
+           return op
+
+arrow :: IParser String
+arrow = string "->" <|> string "\8594" <?> "arrow (->)"
+
+
+commitIf check p = commit <|> try p
+    where commit = do (try $ lookAhead check) >> p
+
+spaceySepBy1 :: IParser b -> IParser a -> IParser [a]
+spaceySepBy1 sep p = do
+  a <- p
+  (a:) <$> many (commitIf (whitespace >> sep) (whitespace >> sep >> whitespace >> p))
+
+
+commaSep1 :: IParser a -> IParser [a]
+commaSep1 = spaceySepBy1 (char ',' <?> "comma ','")
+
+commaSep :: IParser a -> IParser [a]
+commaSep = option [] . commaSep1
+
+semiSep1 :: IParser a -> IParser [a]
+semiSep1 = spaceySepBy1 (char ';' <?> "semicolon ';'")
+
+pipeSep1 :: IParser a -> IParser [a]
+pipeSep1 = spaceySepBy1 (char '|' <?> "type divider '|'")
+
+consSep1 :: IParser a -> IParser [a]
+consSep1 = spaceySepBy1 (char ':' <?> "cons operator ':'")
+
+dotSep1 :: IParser a -> IParser [a]
+dotSep1 p = (:) <$> p <*> many (try (char '.') >> p)
+
+spaceSep1 :: IParser a -> IParser [a]
+spaceSep1 p =  (:) <$> p <*> spacePrefix p
+
+spacePrefix p = many (try (whitespace >> indented >> p))
+
+followedBy a b = do x <- a ; b ; return x
+
+betwixt a b c = do char a ; out <- c
+                   char b <?> "closing '" ++ [b] ++ "'" ; return out
+
+surround a z name p = do
+  char a ; whitespace ; v <- p ; whitespace
+  char z <?> unwords ["closing", name, show z]
+  return v
+
+braces   :: IParser a -> IParser a
+braces   = surround '[' ']' "brace"
+
+parens   :: IParser a -> IParser a
+parens   = surround '(' ')' "paren"
+
+brackets :: IParser a -> IParser a
+brackets = surround '{' '}' "bracket"
+
+accessible :: IParser Expr -> IParser Expr
+accessible expr = do
+  e <- expr
+  access <- optionMaybe . try $
+                  (do { char '.' ; notFollowedBy (char '.') } <?> "field access (e.g. List.map)")
+  case access of
+    Just _  -> accessible (Access e `liftM` var <?> "field access (e.g. List.map)")
+    Nothing -> return e
+
+
+spaces :: IParser String
+spaces = many1 ((multiComment <|> string " " <?> "") >> return ' ') <?> "spaces"
+
+forcedWS :: IParser [String]
+forcedWS = try (do { spaces; many nl_space }) <|> try (many1 nl_space)
+    where nl_space = try $ many1 newline >> spaces
+
+whitespace :: IParser ()
+whitespace = optional forcedWS <?> ""
+
+freshLine :: IParser [[String]]
+freshLine = try (do { many1 newline; many space_nl }) <|> try (many1 space_nl) <?> ""
+    where space_nl = try $ spaces >> many1 newline
+
+newline :: IParser String
+newline = simpleNewline <|> lineComment <?> ""
+
+simpleNewline :: IParser String
+simpleNewline = try (string "\r\n") <|> string "\n"
+
+lineComment :: IParser String
+lineComment = do try (string "--")
+                 manyTill anyChar $ simpleNewline <|> (eof >> return "\n")
+
+multiComment :: IParser String
+multiComment = do { try (string "{-"); closeComment }
+
+closeComment :: IParser String
+closeComment = manyTill anyChar . choice $
+               [ try (string "-}") <?> "close comment"
+               , do { try $ string "{-"; closeComment; closeComment }
+               ]
diff --git a/src/Parse/Modules.hs b/src/Parse/Modules.hs
new file mode 100644
--- /dev/null
+++ b/src/Parse/Modules.hs
@@ -0,0 +1,47 @@
+
+module Parse.Modules (moduleDef, imports) where
+
+import Control.Applicative ((<$>), (<*>))
+import Data.List (intercalate)
+import Text.Parsec hiding (newline,spaces)
+
+import Ast
+import Parse.Library
+
+varList ::  IParser [String]
+varList = parens $ commaSep1 (var <|> parens symOp)
+
+moduleDef :: IParser ([String], [String])
+moduleDef = do
+  try (reserved "module")
+  whitespace
+  names <- dotSep1 capVar <?> "name of module"
+  whitespace
+  exports <- option [] varList
+  whitespace <?> "reserved word 'where'"
+  reserved "where"
+  return (names, exports)
+
+imports :: IParser Imports
+imports = option [] ((:) <$> import' <*> many (try (freshLine >> import')))
+
+
+import' :: IParser (String, ImportMethod)
+import' = do
+  reserved "import"
+  whitespace
+  name <- intercalate "." <$> dotSep1 capVar
+  method <- option (Hiding []) $ try (whitespace >>
+                                      (as' <|> hiding' <|> importing'))
+  return (name, method)
+
+
+as' :: IParser ImportMethod
+as' = reserved "as" >> whitespace >> As <$> capVar <?> "alias for module"
+
+hiding' :: IParser ImportMethod
+hiding' = reserved "hiding" >> whitespace >>
+          Hiding <$> varList <?> "listing of hidden values"
+
+importing' :: IParser ImportMethod
+importing' = Importing <$> varList <?> "listing of imported values (x,y,z)"
diff --git a/src/Parse/ParseExpr.hs b/src/Parse/ParseExpr.hs
deleted file mode 100644
--- a/src/Parse/ParseExpr.hs
+++ /dev/null
@@ -1,138 +0,0 @@
-module ParseExpr (def,term) where
-
-import Ast
-import Control.Applicative ((<$>), (<*>))
-import Control.Monad
-import Data.Char (isSymbol, isDigit)
-import Data.List (foldl')
-import Text.Parsec hiding (newline,spaces)
-import qualified Text.Pandoc as Pan
-
-import ParseLib
-import Patterns
-import Binops
-
-import Guid
-import Types (Type (VarT), Scheme (Forall))
-
-import System.IO.Unsafe
-
-
---------  Basic Terms  --------
-
-numTerm :: (Monad m) => ParsecT [Char] u m Expr
-numTerm = toExpr <$> (preNum <?> "number")
-    where toExpr n | '.' `elem` n = FloatNum (read n)
-                   | otherwise = IntNum (read n)
-          preNum  = (++) <$> many1 digit <*> option "" postNum
-          postNum = do try $ lookAhead (string "." >> digit)
-                       string "."
-                       ('.':) <$> many1 digit
-
-strTerm :: (Monad m) => ParsecT [Char] u m Expr
-strTerm = liftM Str . expecting "string" . betwixt '"' '"' . many $
-          backslashed <|> satisfy (/='"')
-
-varTerm :: (Monad m) => ParsecT [Char] u m Expr
-varTerm = toVar <$> var <?> "variable"
-
-toVar v = case v of "True"  -> Boolean True
-                    "False" -> Boolean False
-                    _       -> Var v
-
-chrTerm :: (Monad m) => ParsecT [Char] u m Expr
-chrTerm = Chr <$> betwixt '\'' '\'' (backslashed <|> satisfy (/='\''))
-          <?> "character"
-
-
---------  Complex Terms  --------
-
-listTerm = (do { try $ string "[markdown|"
-               ; md <- filter (/='\r') <$> manyTill anyChar (try $ string "|]")
-               ; return . Markdown $ Pan.readMarkdown Pan.defaultParserState md })
-           <|> (braces $ choice
-                [ try $ do { lo <- expr; whitespace; string ".." ; whitespace
-                           ; Range lo <$> expr }
-                , list <$> commaSep expr ])
-
-parensTerm = parens $ choice
-             [ do op <- anyOp
-                  return . Lambda "x" . Lambda "y" $ Binop op (Var "x") (Var "y")
-             , do let comma = char ',' <?> "comma ','"
-                  commas <- comma >> many (whitespace >> comma)
-                  let vars = map (('v':) . show) [ 0 .. length commas + 1 ]
-                  return $ foldr Lambda (tuple $ map Var vars) (vars)
-             , do es <- commaSep expr
-                  return $ case es of { [e] -> e; _ -> tuple es }
-             ]
-
-term = choice [ numTerm, strTerm, chrTerm
-              , accessible varTerm
-              , listTerm, parensTerm ]
-       <?> "basic term (4, x, 'c', etc.)"
-
---------  Applications  --------
-
-appExpr = do
-  tlist <- spaceSep1 term
-  return $ case tlist of
-             t:[] -> t
-             t:ts -> foldl' App t ts
-
---------  Normal Expressions  --------
-
-binaryExpr = binops appExpr anyOp
-
-ifExpr = do reserved "if"   ; whitespace ; e1 <- expr ; whitespace
-            reserved "then" ; whitespace ; e2 <- expr ; (whitespace <?> "an 'else' branch")
-            reserved "else" <?> "an 'else' branch" ; whitespace ; If e1 e2 <$> expr
-
-lambdaExpr = do char '\\' <|> char '\x03BB' <?> "anonymous function"
-                whitespace
-                pats <- spaceSep1 patternTerm
-                whitespace ; arrow ; whitespace
-                e <- expr
-                return $ makeLambda pats e
-
-defSet = do
-  brace <- optionMaybe $ do
-             char '{' <?> "a set of definitions { x = ... ; y = ... }"
-  whitespace
-  case brace of
-    Nothing  -> assignExpr
-    Just '{' -> do dss <- semiSep1 assignExpr
-                   whitespace
-                   string "}" <?> "closing bracket '}'"
-                   return (concat dss)
-letExpr = do
-  reserved "let" ; whitespace
-  defs <- defSet
-  whitespace ; reserved "in" ; whitespace
-  Let defs <$> expr
-
-caseExpr = do
-  reserved "case"; whitespace; e <- expr; whitespace; reserved "of"; whitespace
-  Case e <$> brackets (semiSep1 (case_ <?> "cases { x -> ... }"))
-    where case_ = do p <- patternExpr; whitespace; arrow; whitespace
-                     (,) p <$> expr
-
-expr = choice [ ifExpr, letExpr, caseExpr
-              , lambdaExpr, binaryExpr ] <?> "an expression"
-
-assignExpr = do
-  patterns <-
-      choice [ try $ do v <- PVar <$> lowVar
-                        notFollowedBy (whitespace >> char ':')
-                        (v:) <$> spacePrefix patternTerm
-             , (:[]) <$> patternExpr
-             ] <?> "the definition of a variable (x = ...)"
-  whitespace; string "="; whitespace; exp <- expr
-  flattenPatterns patterns exp
-
-def = map (\(Definition n as e) -> Def n as e) <$> assignExpr
-
-
-parseDef str =
-    case parse def "" str of
-      Right result -> Right result
-      Left err -> Left $ "Parse error at " ++ show err
diff --git a/src/Parse/ParseForeign.hs b/src/Parse/ParseForeign.hs
deleted file mode 100644
--- a/src/Parse/ParseForeign.hs
+++ /dev/null
@@ -1,61 +0,0 @@
-
-module ParseForeign (foreignDef) where
-
-import Control.Applicative ((<$>), (<*>))
-import Data.Either (partitionEithers)
-import Text.Parsec hiding (newline,spaces)
-
-import Ast
-import ParseLib
-import ParseExpr (term)
-import ParseTypes
-import Types (signalOf)
-
-
-foreignDef = do try (reserved "foreign") ; whitespace
-                importEvent <|> exportEvent
-
-exportEvent = do
-  try (reserved "export" >> whitespace >> reserved "jsevent" >> whitespace)
-  js   <- jsVar    ; whitespace
-  elm  <- lowVar   ; whitespace
-  string "::"      ; whitespace
-  tipe <- typeExpr
-  case tipe of
-    ADTPT "Signal" [pt] ->
-        either fail (return . ExportEvent js elm . signalOf) (toForeignType pt)
-    _ -> fail "When exporting events, the exported value must be a Signal."
-
-importEvent = do
-  try (reserved "import" >> whitespace >> reserved "jsevent" >> whitespace)
-  js   <- jsVar ; whitespace
-  base <- term <?> "Base case for imported signal (signals cannot be undefined)"
-  whitespace
-  elm  <- lowVar <?> "Name of imported signal"
-  whitespace ; string "::" ; whitespace
-  tipe <- typeExpr
-  case tipe of
-    ADTPT "Signal" [pt] ->
-        either fail (return . ImportEvent js base elm . signalOf) (toForeignType pt)
-    _ -> fail "When importing events, the imported value must be a Signal."
-
-
-jsVar :: (Monad m) => ParsecT [Char] u m String
-jsVar = betwixt '"' '"' $ do
-  v <- (:) <$> (letter <|> char '_') <*> many (alphaNum <|> char '_')
-  if v `notElem` jsReserveds then return v else
-      fail $ "'" ++ v ++
-          "' is not a good name for a importing or exporting JS values."
-
-jsReserveds =
-    [ "null", "undefined", "Nan", "Infinity", "true", "false", "eval"
-    , "arguments", "int", "byte", "char", "goto", "long", "final", "float"
-    , "short", "double", "native", "throws", "boolean", "abstract", "volatile"
-    , "transient", "synchronized", "function", "break", "case", "catch"
-    , "continue", "debugger", "default", "delete", "do", "else", "finally"
-    , "for", "function", "if", "in", "instanceof", "new", "return", "switch"
-    , "this", "throw", "try", "typeof", "var", "void", "while", "with", "class"
-    , "const", "enum", "export", "extends", "import", "super", "implements"
-    , "interface", "let", "package", "private", "protected", "public"
-    , "static", "yield"
-    ]
diff --git a/src/Parse/ParseLib.hs b/src/Parse/ParseLib.hs
deleted file mode 100644
--- a/src/Parse/ParseLib.hs
+++ /dev/null
@@ -1,143 +0,0 @@
-
-module ParseLib where
-
-import Ast
-import Control.Applicative ((<$>),(<*>))
-import Control.Monad
-import Data.Char (isSymbol)
-import Text.Parsec hiding (newline,spaces)
-
-reserveds = [ "if", "then", "else"
-            , "case", "of", "data"
-            , "let", "in"
-            , "module", "where"
-            , "import", "as", "hiding"
-            , "export", "foreign" ]
-
-expecting = flip (<?>)
-
-backslashed :: (Monad m) => ParsecT [Char] u m Char
-backslashed = do { char '\\'; c <- anyChar
-                 ; return . read $ ['\'','\\',c,'\''] }
-
-var :: (Monad m) => ParsecT [Char] u m String
-var = makeVar (letter <|> char '_' <?> "variable")
-
-lowVar :: (Monad m) => ParsecT [Char] u m String
-lowVar = makeVar (lower <?> "lower case variable")
-capVar :: (Monad m) => ParsecT [Char] u m String
-capVar = makeVar (upper <?> "upper case variable")
-
-innerVarChar :: (Monad m) => ParsecT [Char] u m Char
-innerVarChar = alphaNum <|> char '_' <|> char '\'' <?> "" 
-
-makeVar p = do v <- (:) <$> p <*> many innerVarChar
-               guard (v `notElem` reserveds)
-               return v
-
-reserved word =
-  try (string word >> notFollowedBy innerVarChar) >> return word
-  <?> "reserved word '" ++ word ++ "'"
-
-anyOp :: (Monad m) => ParsecT [Char] u m String
-anyOp = betwixt '`' '`' var <|>
-        (do op <- many1 (satisfy isSymbol <|> oneOf "+-/*=.$<>:&|^?%#@~!")
-            guard (op `notElem` [ "=", "..", "->", "--" ])
-            return op) <?> "infix operator (e.g. +, *, ||)"
-
-arrow :: (Monad m) => ParsecT [Char] u m String
-arrow = string "->" <|> string "\8594" <?> "arrow (->)"
-
-
-commitIf check p = commit <|> try p
-    where commit = do (try $ lookAhead check) >> p
-
-spaceySepBy1 :: (Monad m) => ParsecT [Char] u m b -> ParsecT [Char] u m a -> ParsecT [Char] u m [a]
-spaceySepBy1 sep p = do
-  a <- p
-  (a:) <$> many (commitIf (whitespace >> sep) (whitespace >> sep >> whitespace >> p))
-
-
-commaSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
-commaSep1 = spaceySepBy1 (char ',' <?> "comma ','")
-
-commaSep :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
-commaSep = option [] . commaSep1
-
-semiSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
-semiSep1 = spaceySepBy1 (char ';' <?> "semicolon ';'")
-
-pipeSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
-pipeSep1 = spaceySepBy1 (char '|' <?> "type divider '|'")
-
-consSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
-consSep1 = spaceySepBy1 (char ':' <?> "cons operator ':'")
-
-dotSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
-dotSep1 p = (:) <$> p <*> many (try (char '.') >> p)
-
-spaceSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
-spaceSep1 p =  (:) <$> p <*> spacePrefix p
-
-spacePrefix p = many (commitIf (whitespace >> (char '[' <|> char '(')) (whitespace >> p))
-
-followedBy a b = do x <- a ; b ; return x
-
-betwixt a b c = do char a ; out <- c
-                   char b <?> "closing '" ++ [b] ++ "'" ; return out
-
-surround a z name p = do
-  char a ; whitespace ; a <- p ; whitespace
-  char z <?> unwords ["closing", name, show z]
-  return a
-
-braces   :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
-braces   = surround '[' ']' "brace"
-
-parens   :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
-parens   = surround '(' ')' "paren"
-
-brackets :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
-brackets = surround '{' '}' "bracket"
-
-accessible expr = do
-  e <- expr
-  access <- optionMaybe . try $
-                  (do { char '.' ; notFollowedBy (char '.') } <?> "field access (e.g. List.map)")
-  case access of
-    Just _  -> accessible (Access e `liftM` var <?> "field access (e.g. List.map)")
-    Nothing -> return e
-
-
-spaces :: (Monad m) => ParsecT [Char] u m String
-spaces = many1 ((multiComment <|> string " " <?> "") >> return ' ') <?> "spaces"
-
-forcedWS :: (Monad m) => ParsecT [Char] u m [String]
-forcedWS = try (do { spaces; many nl_space }) <|> try (many1 nl_space)
-    where nl_space = try $ many1 newline >> spaces
-
-whitespace :: (Monad m) => ParsecT [Char] u m ()
-whitespace = optional forcedWS <?> ""
-
-freshLine :: (Monad m) => ParsecT [Char] u m [[String]]
-freshLine = try (do { many1 newline; many space_nl }) <|> try (many1 space_nl) <?> ""
-    where space_nl = try $ spaces >> many1 newline
-
-newline :: (Monad m) => ParsecT [Char] u m String
-newline = simpleNewline <|> lineComment <?> ""
-
-simpleNewline :: (Monad m) => ParsecT [Char] u m String
-simpleNewline = try (string "\r\n") <|> string "\n"
-
-lineComment :: (Monad m) => ParsecT [Char] u m String
-lineComment = do try (string "--")
-                 manyTill anyChar $ simpleNewline <|> (eof >> return "\n")
-
-multiComment :: (Monad m) => ParsecT [Char] u m String
-multiComment = do { try (string "{-"); closeComment }
-
-closeComment :: (Monad m) => ParsecT [Char] u m String
-closeComment = manyTill anyChar . choice $
-               [ try (string "-}") <?> "close comment"
-               , do { try $ string "{-"; closeComment; closeComment }
-               ]
diff --git a/src/Parse/ParseModules.hs b/src/Parse/ParseModules.hs
deleted file mode 100644
--- a/src/Parse/ParseModules.hs
+++ /dev/null
@@ -1,44 +0,0 @@
-
-module ParseModules (moduleDef, imports) where
-
-import Control.Applicative ((<$>), (<*>))
-import Data.List (intercalate)
-import Text.Parsec hiding (newline,spaces)
-
-import Ast
-import ParseLib
-
-moduleDef :: (Monad m) => ParsecT [Char] u m ([String], [String])
-moduleDef = do
-  try (reserved "module")
-  whitespace <?> "name of module"
-  names <- dotSep1 capVar
-  whitespace
-  exports <- option [] . parens $ commaSep var
-  whitespace <?> "reserved word 'where'"
-  reserved "where"
-  return (names, exports)
-
-imports :: (Monad m) => ParsecT [Char] u m Imports
-imports = option [] ((:) <$> import' <*> many (try (freshLine >> import')))
-
-
-import' :: (Monad m) => ParsecT [Char] u m (String, ImportMethod)
-import' = do
-  reserved "import"
-  whitespace
-  name <- intercalate "." <$> dotSep1 capVar
-  method <- option (Hiding []) $ try (whitespace >>
-                                      (as' <|> hiding' <|> importing'))
-  return (name, method)
-
-
-as' :: (Monad m) => ParsecT [Char] u m ImportMethod
-as' = reserved "as" >> whitespace >> As <$> capVar <?> "alias for module"
-
-hiding' :: (Monad m) => ParsecT [Char] u m ImportMethod
-hiding' = reserved "hiding" >> whitespace >>
-          Hiding <$> parens (commaSep1 var) <?> "listing of hidden values"
-
-importing' :: (Monad m) => ParsecT [Char] u m ImportMethod
-importing' = Importing <$> parens (commaSep1 var) <?> "listing of imported values (x,y,z)"
diff --git a/src/Parse/ParseTypes.hs b/src/Parse/ParseTypes.hs
deleted file mode 100644
--- a/src/Parse/ParseTypes.hs
+++ /dev/null
@@ -1,102 +0,0 @@
-module ParseTypes where
-
-import Ast
-import Control.Applicative ((<$>),(<*>))
-import Control.Monad (liftM,mapM)
-import Data.Char (isUpper,isLower)
-import Data.Maybe (fromMaybe)
-import Data.List (lookup)
-import Text.Parsec
-
-import ParseLib
-import Types hiding (string,parens)
-import Guid
-
-data ParseType = VarPT String
-               | LambdaPT ParseType ParseType
-               | ADTPT String [ParseType]
-
-listPT t = ADTPT "List" [t]
-tuplePT ts = ADTPT ("Tuple" ++ show (length ts)) ts
-
-typeVar :: (Monad m) => ParsecT [Char] u m ParseType
-typeVar = VarPT <$> lowVar <?> "type variable"
-
-typeList :: (Monad m) => ParsecT [Char] u m ParseType
-typeList  = listPT <$> braces typeExpr
-
-typeTuple :: (Monad m) => ParsecT [Char] u m ParseType
-typeTuple = do ts <- parens (commaSep typeExpr)
-               return $ case ts of { [t] -> t ; _ -> tuplePT ts }
-
-typeUnambiguous :: (Monad m) => ParsecT [Char] u m ParseType
-typeUnambiguous = typeList <|> typeTuple
-
-typeSimple :: (Monad m) => ParsecT [Char] u m ParseType
-typeSimple = dealias <$> var
-    where dealias "String" = listPT (VarPT "Char")
-          dealias v = VarPT v
-
-typeApp :: (Monad m) => ParsecT [Char] u m ParseType
-typeApp = do name <- capVar <?> "type constructor"
-             args <- spacePrefix (typeUnambiguous <|> typeSimple)
-             return $ case args of
-                        [] -> VarPT name
-                        _  -> ADTPT name args
-
-typeExpr :: (Monad m) => ParsecT [Char] u m ParseType
-typeExpr = do
-  t1 <- typeVar <|> typeApp <|> typeUnambiguous
-  whitespace ; arr <- optionMaybe arrow ; whitespace
-  case arr of Just _  -> LambdaPT t1 <$> typeExpr
-              Nothing -> return t1
-
-typeConstructor :: (Monad m) => ParsecT [Char] u m (String, [ParseType])
-typeConstructor = (,) <$> (capVar <?> "another type constructor")
-                      <*> spacePrefix (typeSimple <|> typeUnambiguous)
-
-datatype :: (Monad m) => ParsecT [Char] u m Statement
-datatype = do
-  reserved "data" <?> "datatype definition (data T = A | B | ...)"
-  forcedWS ; name <- capVar <?> "name of data-type" ; args <- spacePrefix lowVar
-  whitespace ; string "=" ; whitespace
-  tcs <- pipeSep1 typeConstructor
-  case toDatatype name args tcs of
-    Right dt -> return dt
-    Left msg -> fail msg
-
-beta = liftM VarT guid
-
-toDatatype name args tcs = Datatype name [1..n] <$> mapM toC tcs
-    where n = length args
-          tvarDict = zip args [1..n]
-          toC (name,pt) = (,) name <$> mapM toT pt
-          toT (LambdaPT t1 t2)  = (==>) <$> toT t1 <*> toT t2
-          toT (ADTPT name args) = ADT name <$> mapM toT args
-          toT (VarPT x@(c:_))
-              | isLower c = VarT <$> case lookup x tvarDict of
-                                       Just v -> Right v
-                                       Nothing -> Left $ msg x
-              | otherwise = return $ ADT x []
-          msg x = "Type variable '" ++ x ++
-                  "' is unbound in type constructor '" ++ name ++ "'."
-
-
-toForeignType (LambdaPT t1 t2) =
-    fail $ "Elm's JavaScript event interface does not yet handle functions. " ++
-           "Only simple values can be imported and exported in this release."
-    --LambdaT <$> toForeignType t1 <*> toForeignType t2
-toForeignType (ADTPT name args)
-    | isJsStructure name =  ADT name <$> mapM toForeignType args
-    | otherwise =
-        Left $ "'" ++ name ++ "' is not an exportable type " ++
-               "constructor. Only 'JSArray' and 'JSTupleN' are exportable."
-
-toForeignType (VarPT x@(c:_))
-    | isLower c =
-        Left "All exported types must be concrete types (JSNumber, JSString, etc.)"
-    | x `elem` ["JSString","JSNumber","JSElement","JSBool"] = Right (ADT x [])
-    | otherwise = Left $ "'" ++ x ++ "' is not an exportable type. Only JSTypes are exportable."
-
-isJsStructure name = name == "JSArray" || isTuple
-    where isTuple = "JSTuple" == take 7 name && drop 7 name `elem` map show [2..5]
diff --git a/src/Parse/Parser.hs b/src/Parse/Parser.hs
--- a/src/Parse/Parser.hs
+++ b/src/Parse/Parser.hs
@@ -1,41 +1,41 @@
-module Parser (parseProgram) where
-
-import Ast
-import Control.Applicative ((<$>), (<*>))
-import Control.Monad
-import Data.Char (isSymbol, isDigit)
-import Data.List (foldl')
-import Text.Parsec hiding (newline,spaces)
-
-import ParseLib
-import ParseExpr
-import ParseTypes
-import ParseModules
-import ParseForeign
-
-
-statement =  (:[]) <$> foreignDef
-         <|> (:[]) <$> datatype
-         <|> def
-         <?> "datatype or variable definition"
-
-freshDef = commitIf (freshLine >> (letter <|> char '_')) $ do
-             freshLine
-             statement <?> "another datatype or variable definition"
-
-defs1 = do d <- statement <?> "at least one datatype or variable definition"
-           concat <$> (d:) <$> many freshDef
-
-program = do
-  optional freshLine
-  (names,exports) <- option (["Main"],[]) (moduleDef `followedBy` freshLine)
-  is <- (do try (lookAhead $ reserved "import")
-            imports `followedBy` freshLine) <|> return []
-  statements <- defs1
-  optional freshLine ; optional spaces ; eof
-  return $ Module names exports is statements
-
-parseProgram source = 
-    case parse program "" source of
-      Right result -> Right result
-      Left err -> Left $ "Parse error at " ++ show err
+module Parse.Parser (parseProgram) where
+
+import Ast
+import Control.Applicative ((<$>), (<*>))
+import Control.Monad
+import Data.Char (isSymbol, isDigit)
+import Data.List (foldl')
+import Text.Parsec hiding (newline,spaces)
+
+import Parse.Library
+import Parse.Expr
+import Parse.Types
+import Parse.Modules
+import Parse.Foreign
+
+
+statement =  (:[]) <$> foreignDef
+         <|> (:[]) <$> datatype
+         <|> def
+         <?> "datatype or variable definition"
+
+freshDef = commitIf (freshLine >> (letter <|> char '_')) $ do
+             freshLine
+             statement <?> "another datatype or variable definition"
+
+defs1 = do d <- statement <?> "at least one datatype or variable definition"
+           concat <$> (d:) <$> many freshDef
+
+program = do
+  optional freshLine
+  (names,exports) <- option (["Main"],[]) (moduleDef `followedBy` freshLine)
+  is <- (do try (lookAhead $ reserved "import")
+            imports `followedBy` freshLine) <|> return []
+  statements <- defs1
+  optional freshLine ; optional spaces ; eof
+  return $ Module names exports is statements
+
+parseProgram source = 
+    case iParse program "" source of
+      Right result -> Right result
+      Left err -> Left $ "Parse error at " ++ show err
diff --git a/src/Parse/Patterns.hs b/src/Parse/Patterns.hs
--- a/src/Parse/Patterns.hs
+++ b/src/Parse/Patterns.hs
@@ -1,33 +1,35 @@
-module Patterns (patternTerm, patternExpr, makeLambda, flattenPatterns) where
+module Parse.Patterns (patternTerm, patternExpr, makeLambda, flattenPatterns) where
 
 import Ast
 import Data.Char (isUpper)
 import Control.Applicative ((<$>),(<*>))
 import Control.Monad
-import Text.Parsec
-import ParseLib
+import Control.Monad.State
+import Text.Parsec hiding (newline,spaces,State)
+import Text.Parsec.Indent
+import Parse.Library
 
-patternBasic :: Monad m => ParsecT [Char] u m Pattern
+patternBasic :: IParser Pattern
 patternBasic =
     choice [ char '_' >> return PAnything
            , do x@(c:_) <- var
                 return $ if isUpper c then PData x [] else PVar x
            ]
 
-patternTuple :: Monad m => ParsecT [Char] u m Pattern
+patternTuple :: IParser Pattern
 patternTuple = do ps <- parens (commaSep patternExpr)
                   return $ case ps of { [p] -> p; _ -> ptuple ps }
 
-patternList :: Monad m => ParsecT [Char] u m Pattern
+patternList :: IParser Pattern
 patternList = plist <$> braces (commaSep patternExpr)
 
-patternTerm :: Monad m => ParsecT [Char] u m Pattern
+patternTerm :: IParser Pattern
 patternTerm = patternTuple <|> patternList <|> patternBasic <?> "pattern"
 
-patternConstructor :: Monad m => ParsecT [Char] u m Pattern
+patternConstructor :: IParser Pattern
 patternConstructor = PData <$> capVar <*> spacePrefix patternTerm
 
-patternExpr :: Monad m => ParsecT [Char] u m Pattern
+patternExpr :: IParser Pattern
 patternExpr = foldr1 pcons <$> consSep1 (patternConstructor <|> patternTerm) <?> "pattern"
 
 
@@ -38,17 +40,22 @@
           func (PVar x)  e = e
           func p e = Case (Var $ getName p) [(p,e)]
 
-flattenPatterns (PVar f : args) exp =
-    return [ Definition f (map getName args) (makeBody args exp) ]
+flattenPatterns (PVar f : args) exp
+    | isOp (head f) = let [a,b] = (map getName args) in
+                      return [ OpDef f a b (makeBody args exp) ]
+    | otherwise     = return [ FnDef f (map getName args) (makeBody args exp) ]
+
+
 flattenPatterns [p] exp = return $ matchSingle p exp p
+
 flattenPatterns ps _ = 
     fail $ "Pattern (" ++ unwords (map show ps) ++
            ") cannot be used on the left-hand side of an assign statement."
 
 matchSingle pat exp p@(PData _ ps) =
-    (Definition v [] exp) : concatMap (matchSingle p $ Var v) ps
+    (FnDef v [] exp) : concatMap (matchSingle p $ Var v) ps
         where v = getName p
-matchSingle pat exp (PVar x)  = [ Definition x [] (Case exp [(pat,Var x)]) ]
+matchSingle pat exp (PVar x)  = [ FnDef x [] (Case exp [(pat,Var x)]) ]
 matchSingle pat exp PAnything = []
 
 getName p = f p
diff --git a/src/Parse/Types.hs b/src/Parse/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Parse/Types.hs
@@ -0,0 +1,104 @@
+module Parse.Types where
+
+import Ast
+import Control.Applicative ((<$>),(<*>))
+import Control.Monad (liftM,mapM)
+import Data.Char (isUpper,isLower)
+import Data.Maybe (fromMaybe)
+import Data.List (lookup)
+import Text.Parsec
+import Text.Parsec.Indent
+
+import Parse.Library
+import Types.Types hiding (string,parens)
+import Guid
+
+data ParseType = VarPT String
+               | LambdaPT ParseType ParseType
+               | ADTPT String [ParseType]
+
+listPT t = ADTPT "List" [t]
+tuplePT ts = ADTPT ("Tuple" ++ show (length ts)) ts
+
+typeVar :: IParser ParseType
+typeVar = VarPT <$> lowVar <?> "type variable"
+
+typeList :: IParser ParseType
+typeList  = listPT <$> braces typeExpr
+
+typeTuple :: IParser ParseType
+typeTuple = do ts <- parens (commaSep typeExpr)
+               return $ case ts of { [t] -> t ; _ -> tuplePT ts }
+
+typeUnambiguous :: IParser ParseType
+typeUnambiguous = typeList <|> typeTuple
+
+typeSimple :: IParser ParseType
+typeSimple = dealias <$> var
+    where dealias "String" = listPT (VarPT "Char")
+          dealias "Time" = VarPT "Float"
+          dealias v = VarPT v
+
+typeApp :: IParser ParseType
+typeApp = do name <- capVar <?> "type constructor"
+             args <- spacePrefix (typeUnambiguous <|> typeSimple)
+             return $ case args of
+                        [] -> VarPT name
+                        _  -> ADTPT name args
+
+typeExpr :: IParser ParseType
+typeExpr = do
+  t1 <- typeVar <|> typeApp <|> typeUnambiguous
+  whitespace ; arr <- optionMaybe arrow ; whitespace
+  case arr of Just _  -> LambdaPT t1 <$> typeExpr
+              Nothing -> return t1
+
+typeConstructor :: IParser (String, [ParseType])
+typeConstructor = (,) <$> (capVar <?> "another type constructor")
+                      <*> spacePrefix (typeSimple <|> typeUnambiguous)
+
+datatype :: IParser Statement
+datatype = do
+  reserved "data" <?> "datatype definition (data T = A | B | ...)"
+  forcedWS ; name <- capVar <?> "name of data-type" ; args <- spacePrefix lowVar
+  whitespace ; string "=" ; whitespace
+  tcs <- pipeSep1 typeConstructor
+  case toDatatype name args tcs of
+    Right dt -> return dt
+    Left msg -> fail msg
+
+beta = liftM VarT guid
+
+toDatatype name args tcs = Datatype name [1..n] <$> mapM toC tcs
+    where n = length args
+          tvarDict = zip args [1..n]
+          toC (name,pt) = (,) name <$> mapM toT pt
+          toT (LambdaPT t1 t2)  = (==>) <$> toT t1 <*> toT t2
+          toT (ADTPT name args) = ADT name <$> mapM toT args
+          toT (VarPT x@(c:_))
+              | isLower c = VarT <$> case lookup x tvarDict of
+                                       Just v -> Right v
+                                       Nothing -> Left $ msg x
+              | otherwise = return $ ADT x []
+          msg x = "Type variable '" ++ x ++
+                  "' is unbound in type constructor '" ++ name ++ "'."
+
+
+toForeignType (LambdaPT t1 t2) =
+    fail $ "Elm's JavaScript event interface does not yet handle functions. " ++
+           "Only simple values can be imported and exported in this release."
+    --LambdaT <$> toForeignType t1 <*> toForeignType t2
+toForeignType (ADTPT name args)
+    | isJsStructure name =  ADT name <$> mapM toForeignType args
+    | otherwise =
+        Left $ "'" ++ name ++ "' is not an exportable type " ++
+               "constructor. Only 'JSArray' and 'JSTupleN' are exportable."
+
+toForeignType (VarPT x@(c:_))
+    | isLower c =
+        Left "All exported types must be concrete types (JSNumber, JSString, etc.)"
+    | x `elem` ["JSString","JSNumber","JSElement","JSBool"] = Right (ADT x [])
+    | otherwise = Left $ "'" ++ x ++ "' is not an exportable type. Only JSTypes are exportable."
+
+isJsStructure name = name == "JSArray" || isTuple
+    where isTuple = "JSTuple" == take 7 name && drop 7 name `elem` map show [2..5]
diff --git a/src/Rename.hs b/src/Rename.hs
--- a/src/Rename.hs
+++ b/src/Rename.hs
@@ -1,119 +1,135 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-module Rename (rename, derename) where
-
-import Ast
-import Control.Arrow (first)
-import Control.Monad (ap, liftM, foldM, mapM, Monad, zipWithM)
-import Control.Monad.State (evalState, State, get, put)
-import Data.Char (isLower,isDigit)
-import Guid
-
-derename var
-    | isDigit (last var) = reverse . tail . dropWhile isDigit $ reverse var
-    | otherwise = var
-
-rename :: Module -> Module
-rename (Module name ex im stmts) =
-    Module name ex im . run $ renameStatements deprime stmts
-
-renameStatements env stmts = do env' <- extends env $ concatMap getNames stmts
-                                mapM (renameStmt env') stmts
-    where getNames stmt = case stmt of Def n _ _ -> [n]
-                                       Datatype _ _ tcs -> map fst tcs
-                                       ImportEvent _ _ n _ -> [n]
-                                       ExportEvent _ _ _ -> []
-          renameStmt env (Def name args e) =
-              do env' <- extends env args
-                 Def (env name) (map env' args) `liftM` rename' env' e
-          renameStmt env (Datatype name args tcs) =
-              return $ Datatype name args $ map (first env) tcs
-          renameStmt env (ImportEvent js base elm tipe) =
-              do base' <- rename' env base
-                 return $ ImportEvent js base' (env elm) tipe
-          renameStmt env (ExportEvent js elm tipe) =
-                 return $ ExportEvent js (env elm) tipe
-
-rename' :: (String -> String) -> Expr -> GuidCounter Expr
-rename' env expr =
-    case expr of
-
-      Range e1 e2 -> Range `liftM` rnm e1
-                              `ap` rnm e2
-      
-      Access e x -> Access `liftM` rnm e
-                              `ap` return x
-
-      Binop op@(h:_) e1 e2 ->
-        let rop = if isLower h || '_' == h
-                  then env op
-                  else op
-        in Binop rop `liftM` rnm e1
-                        `ap` rnm e2
-
-      Lambda x e -> do
-          (rx, env') <- extend env x
-          Lambda rx `liftM` rename' env' e
-
-      App e1 e2 -> App `liftM` rnm e1
-                          `ap` rnm e2
-
-      If e1 e2 e3 -> If `liftM` rnm e1
-                           `ap` rnm e2
-                           `ap` rnm e3
-
-      Lift e es -> Lift `liftM` rnm e
-                           `ap` mapM rnm es
-
-      Fold e1 e2 e3 -> Fold `liftM` rnm e1
-                               `ap` rnm e2
-                               `ap` rnm e3
-
-      Async e -> Async `liftM` rnm e
-
-      Let defs e -> renameLet env defs e
-
-      Var x -> return . Var $ env x
-
-      Data name es -> Data name `liftM` mapM rnm es
-
-      Case e cases -> Case `liftM` rnm e
-                              `ap` mapM (patternRename env) cases
-
-      _ -> return expr
-
-  where rnm = rename' env
-
-deprime = map (\c -> if c == '\'' then '_' else c)
-
-extend :: (String -> String) -> String -> GuidCounter (String, String -> String)
-extend env x = do
-  n <- guid
-  let rx = deprime x ++ "_" ++ show n
-  return (rx, \y -> if y == x then rx else env y)
-
-extends :: (String -> String) -> [String] -> GuidCounter (String -> String)
-extends env xs = foldM (\e x -> liftM snd $ extend e x) env xs
-
-patternExtend :: Pattern -> (String -> String) -> GuidCounter (Pattern, String -> String)
-patternExtend pattern env =
-    case pattern of
-      PAnything -> return (PAnything, env)
-      PVar x -> first PVar `liftM` extend env x
-      PData name ps ->
-          first (PData name . reverse) `liftM` foldM f ([], env) ps
-                 where f (rps,env') p = do (rp,env'') <- patternExtend p env'
-                                           return (rp:rps, env'')
-
-patternRename :: (String -> String) -> (Pattern, Expr) -> GuidCounter (Pattern, Expr)
-patternRename env (p,e) = do
-  (rp,env') <- patternExtend p env
-  re <- rename' env' e
-  return (rp,re)
-
-renameLet env defs e = do env' <- extends env $ map getNames defs
-                          defs' <- mapM (renameDef env') defs
-                          Let defs' `liftM` rename' env' e
-    where getNames (Definition n _ _) = n
-          renameDef env (Definition name args e) =
-              do env' <- extends env args
-                 Definition (env name) (map env' args) `liftM` rename' env' e
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module Rename (renameModule, derename, deprime) where
+
+import Ast
+import Control.Arrow (first)
+import Control.Monad (ap, liftM, foldM, mapM, Monad, zipWithM)
+import Control.Monad.State (evalState, State, get, put)
+import Data.Char (isLower,isDigit)
+import Guid
+
+derename var
+    | isDigit (last var) = reverse . tail . dropWhile isDigit $ reverse var
+    | otherwise = var
+
+renameModule :: Module -> Module
+renameModule modul = run (rename deprime modul)
+
+class Rename a where
+  rename :: (String -> String) -> a -> GuidCounter a
+
+instance Rename Module where 
+  rename env (Module name ex im stmts) = do stmts' <- renameStmts env stmts
+                                            return (Module name ex im stmts')
+
+instance Rename Def where
+  rename env (OpDef op a1 a2 e) =
+      do env' <- extends env [a1,a2]
+         OpDef op (env' a1) (env' a2) `liftM` rename env' e
+  rename env (FnDef f args e) =
+      do env' <- extends env args
+         FnDef (env f) (map env' args) `liftM` rename env' e
+
+instance Rename Statement where
+  rename env (Definition def) = Definition `liftM` rename env def
+  rename env (Datatype name args tcs) =
+      return $ Datatype name args $ map (first env) tcs
+  rename env (ImportEvent js base elm tipe) =
+      do base' <- rename env base
+         return $ ImportEvent js base' (env elm) tipe
+  rename env (ExportEvent js elm tipe) =
+      return $ ExportEvent js (env elm) tipe
+
+renameStmts env stmts = do env' <- extends env $ concatMap getNames stmts
+                           mapM (rename env') stmts
+    where getNames stmt = case stmt of
+                            Definition (FnDef n _ _) -> [n]
+                            Datatype _ _ tcs -> map fst tcs
+                            ImportEvent _ _ n _ -> [n]
+                            _ -> []
+
+instance Rename Expr where
+  rename env expr =
+    let rnm = rename env in
+    case expr of
+
+      Range e1 e2 -> Range `liftM` rnm e1
+                              `ap` rnm e2
+      
+      Access e x -> Access `liftM` rnm e
+                              `ap` return x
+
+      Binop op@(h:_) e1 e2 ->
+        let rop = if isLower h || '_' == h
+                  then env op
+                  else op
+        in Binop rop `liftM` rnm e1
+                        `ap` rnm e2
+
+      Lambda x e -> do
+          (rx, env') <- extend env x
+          Lambda rx `liftM` rename env' e
+
+      App e1 e2 -> App `liftM` rnm e1
+                          `ap` rnm e2
+
+      If e1 e2 e3 -> If `liftM` rnm e1
+                           `ap` rnm e2
+                           `ap` rnm e3
+
+      Guard ps -> Guard `liftM` mapM grnm ps
+              where grnm (b,e) = (,) `liftM` rnm b
+                                        `ap` rnm e
+
+      Lift e es -> Lift `liftM` rnm e
+                           `ap` mapM rnm es
+
+      Fold e1 e2 e3 -> Fold `liftM` rnm e1
+                               `ap` rnm e2
+                               `ap` rnm e3
+
+      Async e -> Async `liftM` rnm e
+
+      Let defs e -> renameLet env defs e
+
+      Var x -> return . Var $ env x
+
+      Data name es -> Data name `liftM` mapM rnm es
+
+      Case e cases -> Case `liftM` rnm e
+                              `ap` mapM (patternRename env) cases
+
+      _ -> return expr
+
+deprime = map (\c -> if c == '\'' then '_' else c)
+
+extend :: (String -> String) -> String -> GuidCounter (String, String -> String)
+extend env x = do
+  n <- guid
+  let rx = deprime x ++ "_" ++ show n
+  return (rx, \y -> if y == x then rx else env y)
+
+extends :: (String -> String) -> [String] -> GuidCounter (String -> String)
+extends env xs = foldM (\e x -> liftM snd $ extend e x) env xs
+
+patternExtend :: Pattern -> (String -> String) -> GuidCounter (Pattern, String -> String)
+patternExtend pattern env =
+    case pattern of
+      PAnything -> return (PAnything, env)
+      PVar x -> first PVar `liftM` extend env x
+      PData name ps ->
+          first (PData name . reverse) `liftM` foldM f ([], env) ps
+                 where f (rps,env') p = do (rp,env'') <- patternExtend p env'
+                                           return (rp:rps, env'')
+
+patternRename :: (String -> String) -> (Pattern, Expr) -> GuidCounter (Pattern, Expr)
+patternRename env (p,e) = do
+  (rp,env') <- patternExtend p env
+  re <- rename env' e
+  return (rp,re)
+
+renameLet env defs e = do env' <- extends env $ concatMap getNames defs
+                          defs' <- mapM (rename env') defs
+                          Let defs' `liftM` rename env' e
+    where getNames (FnDef n _ _)   = [n]
+          getNames (OpDef _ _ _ _) = []
diff --git a/src/Substitute.hs b/src/Substitute.hs
--- a/src/Substitute.hs
+++ b/src/Substitute.hs
@@ -1,6 +1,6 @@
 module Substitute (subst) where
 
-import Control.Arrow (second)
+import Control.Arrow (second, (***))
 
 import Ast
 
@@ -14,12 +14,14 @@
       Lambda x e -> if x == old then expr else Lambda x (f e)
       App e1 e2 -> App (f e1) (f e2)
       If e1 e2 e3 -> If (f e1) (f e2) (f e3)
+      Guard ps -> Guard (map (f *** f) ps)
       Lift e es -> Lift (f e) (map f es)
       Fold e1 e2 e3 -> Fold (f e1) (f e2) (f e3)
       Async e -> Async (f e)
       Input _ -> expr
       Let defs e -> Let (map substDef defs) (f e)
-              where substDef (Definition name vs e) = Definition name vs (f e)
+              where substDef (FnDef name vs e)  = FnDef name vs (f e)
+                    substDef (OpDef op a1 a2 e) = OpDef op a1 a2 (f e)
       Var x -> if x == old then new else expr
       Case e cases -> Case (f e) $ map (second f) cases
       Data name es -> Data name (map f es)
diff --git a/src/Types/Constrain.hs b/src/Types/Constrain.hs
--- a/src/Types/Constrain.hs
+++ b/src/Types/Constrain.hs
@@ -1,15 +1,17 @@
 
 module Types.Constrain (constrain) where
 
-import Ast
-import Types
 import Data.List (foldl',sort,group,isPrefixOf,intercalate,isSuffixOf)
 import qualified Data.Set as Set
 import qualified Data.Map as Map
 import Control.Arrow (second)
 import Control.Monad (liftM,mapM,zipWithM,foldM)
 import Control.Monad.State (evalState)
+
+import Ast
 import Guid
+
+import Types.Types
 import Types.Substitutions
 
 --import System.IO.Unsafe
@@ -44,19 +46,21 @@
 constrain typeHints (Module _ _ imports stmts) = do
   (ass,css,schemess) <- unzip3 `liftM` mapM stmtGen stmts
   hints <- typeHints
-  let aliasHints = getAliases (imports ++ extraImports) hints
-  let allHints = Map.fromList (aliasHints ++ concat schemess)
+  let extraImports = ("Time", Hiding ["read"]) : map (\n -> (n, Hiding []))
+                     ["List","Signal","Text","Graphics","Color"]
+      insert as n = do v <- guid; return $ Map.insertWith' (\_ x -> x) n [v] as
+      aliasHints = getAliases (imports ++ extraImports) hints
+      allHints = Map.fromList (aliasHints ++ concat schemess)
   assumptions <- foldM insert (unionsA ass) $ map fst (concat schemess)
-  findAmbiguous (map fst hints) (map fst aliasHints) assumptions $
-                do let cs = let f k s vs = map (\v -> Context k $ v :<<: s) vs in
-                            concat . Map.elems $ Map.intersectionWithKey f allHints assumptions
-                   let escapees = Map.keys $ Map.difference assumptions allHints
-                   return . Right . (,) escapees $ cs ++ Set.toList (Set.unions css)
-      where extraImports =
-                map (\n -> (n, Hiding [])) ["List","Signal","Text","Graphics","Color"]
-            insert as n = do v <- guid; return $ Map.insertWith' (\_ x -> x) n [v] as
+  findAmbiguous (map fst hints) (map fst aliasHints) assumptions $ do
+    let f k s vs = map (\v -> Context k $ v :<<: s) vs
+        cs = concat . Map.elems $ Map.intersectionWithKey f allHints assumptions
+        escapees = Map.keys $ Map.difference assumptions allHints
+    return . Right . (,) escapees $ cs ++ Set.toList (Set.unions css)
 
-gen :: Expr -> GuidCounter (Map.Map String [X], Set.Set (Context String Constraint), Type)
+gen :: Expr -> GuidCounter (Map.Map String [X],
+                            Set.Set (Context String Constraint),
+                            Type)
 
 gen (Var x) =
     do b <- guid
@@ -81,8 +85,10 @@
     do (as,cs,t) <- gen e
        (ass, schemes) <- liftM unzip (mapM defScheme defs)
        let assumptions = unionsA (as:ass)
-       let names = map (\(Definition x _ _) -> x) defs
-       let genCs name s = do
+           getName (FnDef f _ _) = f
+           getName (OpDef op _ _ _) = op
+           names = map getName defs
+           genCs name s = do
              v <- guid
              let vs = Map.findWithDefault [v] name assumptions
              return $ map (\x -> ctx (Var name) $ x :<<: s) vs
@@ -109,7 +115,11 @@
 
 gen (Data name es) = gen $ foldl' App (Var name) es
 gen (Binop op e1 e2) = gen (Var op `App` e1 `App` e2)
-gen (Access (Var x) y) = gen . Var $ x ++ "." ++ y
+
+gen (Access (Var a) b) = gen . Var $ a ++ "." ++ b
+gen (Access (Access (Var a) b) c) = gen . Var $ intercalate "." [a, b, c]
+gen (Access (Access (Access (Var a) b) c) d) = gen . Var $ intercalate "." [a, b, c, d]
+
 gen (Range e1 e2) =
     do (a1,c1,t1) <- gen e1
        (a2,c2,t2) <- gen e2
@@ -118,6 +128,16 @@
                                                   , ctx e2 (t2 :=: int) ] ]
               , listOf int )
 
+gen e@(Guard ps) = do (ass,css,t:ts) <- unzip3 `liftM` mapM genPair ps
+                      let cs = Set.fromList (map (ctx e . (t :=:)) ts)
+                      return (unionsA ass, Set.unions (cs:css), t)
+    where genPair (b,e) = do 
+            (a1,c1,t1) <- gen b
+            (a2,c2,t2) <- gen e
+            return ( unionsA [a1,a2]
+                   , Set.unions [ c1, c2, Set.singleton (ctx b (t1 :=: bool)) ]
+                   , t2 )
+
 gen other =
     case other of
       IntNum _ -> do t <- beta
@@ -127,7 +147,7 @@
       Str _ -> primitive string
       Boolean _ -> primitive bool
       Markdown _ -> primitive element
-      _ -> beta >>= primitive 
+      -- _ -> beta >>= primitive 
 
 primitive t = return (Map.empty, Set.empty, t)
 
@@ -157,43 +177,45 @@
          , ts ++ [output] )
 
 
-defScheme :: Definition -> GuidCounter (Map.Map String [X], Scheme)
-defScheme (Definition name args e) = do
-  (as,cs,hint) <- defGen name args e
-  return ( as, snd hint )
+defScheme :: Def -> GuidCounter (Map.Map String [X], Scheme)
+defScheme def = do (as,cs,hint) <- defGen def
+                   return ( as, snd hint )
 
-defGen name args e = do
-  argDict <- mapM (\a -> liftM ((,) a) guid) args 
-  (as,cs,t) <- gen e
-  let genCs (arg,x) = do
-        v <- guid
-        return . map (\y -> Context arg $ VarT x :=: VarT y) $ Map.findWithDefault [v] arg as
-  cs' <- concat `liftM` mapM genCs argDict
-  let as' = foldr Map.delete as args
-  let tipe = foldr (==>) t $ map (VarT . snd) argDict
-  scheme <- generalize (concat $ Map.elems as') $
-            Forall (map snd argDict) (cs' ++ Set.toList cs) tipe
-  return ( as', Set.empty, (name, scheme) )
+defGen def = case def of FnDef f args e -> defGen' f args e
+                         OpDef op a1 a2 e -> defGen' op [a1,a2] e
+    where defGen' name args e = do
+            argDict <- mapM (\a -> liftM ((,) a) guid) args 
+            (as,cs,t) <- gen e
+            let as' = foldr Map.delete as args
+                tipe = foldr (==>) t $ map (VarT . snd) argDict
+                genCs (arg,x) = do
+                  v <- guid
+                  let as' = Map.findWithDefault [v] arg as
+                  return $ map (\y -> Context arg $ VarT x :=: VarT y) as'
+            cs' <- concat `liftM` mapM genCs argDict
+            scheme <- generalize (concat $ Map.elems as') $
+                      Forall (map snd argDict) (cs' ++ Set.toList cs) tipe
+            return ( as', Set.empty, (name, scheme) )
 
-stmtGen (Def name args e) = do (as,cs,hint) <- defGen name args e
-                               return ( as, cs, [hint] )
+stmtGen (Definition def) = do (as,cs,hint) <- defGen def
+                              return ( as, cs, [hint] )
 
 stmtGen (Datatype name xs tcs) = do schemes <- mapM gen' tcs'
                                     return (Map.empty, Set.empty, schemes)
-    where names = map (+ (length xs)) [1..5]
-          tcs' = map (second . map $ rnm names) tcs
-          supers t = map (Context name) $ zipWith (:<:) (map VarT names)
-                     [ number, time, appendable t, comparable, transformable ]
+    where var n = length xs + n
+          ( a, b, c) = ( var 1,  var 2,  var 3)
+          (va,vb,vc) = (VarT a, VarT b, VarT c)
+          rnm (ADT n []) | n == "Number"     = va
+                         | n == "Appendable" = vb
+                         | n == "Comparable" = vc
+          rnm t = t
+          tcs' = map (second (map rnm)) tcs
+          supers t = map (Context name) $
+                     zipWith (:<:) [va,vb,vc] [number,appendable t,comparable]
           gen' (n,ts) = do t <- beta
-                           let s = Forall (xs ++ names) (supers t) $
+                           let s = Forall (xs ++ [a,b,c]) (supers t) $
                                    foldr (==>) (ADT name $ map VarT xs) ts
                            (,) n `liftM` generalize [] s
-          rnm [a,b,c,d,e] (ADT n []) | n == "Number" = VarT a
-                                     | n == "Time"  = VarT b
-                                     | n == "Appendable"  = VarT c
-                                     | n == "Comparable"  = VarT d
-                                     | n == "Transformable"  = VarT e
-          rnm _ t = t
 
 stmtGen (ExportEvent js elm tipe) = do
   x <- guid
diff --git a/src/Types/Hints.hs b/src/Types/Hints.hs
--- a/src/Types/Hints.hs
+++ b/src/Types/Hints.hs
@@ -3,7 +3,7 @@
 
 import Control.Monad (liftM,mapM)
 import Control.Arrow (first)
-import Types
+import Types.Types
 import Types.Substitutions (rescheme)
 
 
@@ -142,6 +142,7 @@
 
 --------  Signals  --------
 
+lyft n = sig (n+1) ("lift" ++ show n)
 sig n name = (,) name $ Forall [1..n] [] (fn ts ==> fn (map signalOf ts))
     where fn = foldr1 (==>)
           ts = map VarT [1..n]
@@ -149,19 +150,23 @@
 signals = prefix "Signal"
     [ sig 1 "constant"
     , sig 2 "lift" 
-    , sig 3 "lift2"
-    , sig 4 "lift3"
-    , sig 5 "lift4"
-    , "foldp"     -:: (a ==> b ==> b) ==> b ==> signalOf a ==> signalOf b
+    ] ++ map lyft [2..8] ++ [
+      "foldp"     -:: (a ==> b ==> b) ==> b ==> signalOf a ==> signalOf b
     , "foldp1"    -:: (a ==> a ==> a) ==> signalOf a ==> signalOf a
     , "foldp'"    -:: (a ==> b ==> b) ==> (a ==> b) ==> signalOf a ==> signalOf b
     , "count"     -:: signalOf a ==> signalOf int
-    , "keepIf"    -:: (a==>bool) ==> a ==> signalOf a ==> signalOf a
-    , "dropIf"    -:: (a==>bool) ==> a ==> signalOf a ==> signalOf a
+    , "countIf"   -:: (a ==> bool) ==> signalOf a ==> signalOf int
+    , "keepIf"    -:: (a ==> bool) ==> a ==> signalOf a ==> signalOf a
+    , "dropIf"    -:: (a ==> bool) ==> a ==> signalOf a ==> signalOf a
     , "keepWhen"  -:: signalOf bool ==> a ==> signalOf a ==> signalOf a
     , "dropWhen"  -:: signalOf bool ==> a ==> signalOf a ==> signalOf a
     , "dropRepeats" -:: signalOf a ==> signalOf a
-    , "sampleOn" -:: signalOf a ==> signalOf b ==> signalOf b
+    , "sampleOn"  -:: signalOf a ==> signalOf b ==> signalOf b
+    , "timestamp" -:: signalOf a ==> signalOf (tupleOf [time,a])
+    , "timeOf"    -:: signalOf a ==> signalOf time
+    , "merge"     -:: signalOf a ==> signalOf a ==> signalOf a
+    , "merges"    -:: listOf (signalOf a) ==> signalOf a
+    , numScheme (\n -> int ==> signalOf n ==> signalOf float) "average"
     ]
 
 http = prefix "HTTP"
@@ -179,11 +184,8 @@
 concreteSignals = 
   [ "Keyboard.Raw.keysDown"    -: signalOf (listOf int)
   , "Keyboard.Raw.charPressed" -: signalOf (maybeOf int)
-  , "Random.inRange"     -: int ==> int ==> signalOf int
-  , "Random.randomize"   -:: int ==> int ==> signalOf a ==> signalOf int
-  , timeScheme "Time.every"  (\t -> t ==> signalOf t)
-  , timeScheme "Time.before" (\t -> t ==> signalOf bool)
-  , timeScheme "Time.after"  (\t -> t ==> signalOf bool)
+  , "Random.inRange"    -: int ==> int ==> signalOf int
+  , "Random.randomize"  -:: int ==> int ==> signalOf a ==> signalOf int
   , "Window.dimensions" -: signalOf point
   , "Window.width"      -: signalOf int
   , "Window.height"     -: signalOf int
@@ -202,6 +204,40 @@
   , "Input.dropDown"    -:: listOf (tupleOf [string,a]) ==> tupleOf [element, signalOf a]
   ]
 
+times = prefix "Time"
+  [ "fps"     -: number ==> signalOf time
+  , "every"   -: time ==> signalOf time
+  , "fpsWhen" -: number ==> signalOf bool ==> signalOf time
+  , "delay"   -:: time ==> signalOf a ==> signalOf a
+  , "since"   -:: time ==> signalOf a ==> signalOf bool
+  , "hour"    -: time
+  , "minute"  -: time
+  , "second"  -: time
+  , "ms"      -: time
+  , "inHours"   -: time ==> float
+  , "inMinutes" -: time ==> float
+  , "inSeconds" -: time ==> float
+  , "inMss"  -: time ==> float
+  , "toDate"  -: time ==> date
+  , "read"    -: string ==> maybeOf time
+  ]
+
+dates =
+  let days   = map (-: day) ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
+      months = map (-: month) [ "Jan", "Feb", "Mar", "Apr", "May", "Jun"
+		              , "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
+  in  prefix "Date"
+        ([ "read"      -: string ==> maybeOf date
+         , "year"      -: date ==> int
+         , "month"     -: date ==> month
+         , "day"       -: date ==> int
+         , "hour"      -: date ==> int
+         , "minute"    -: date ==> int
+         , "second"    -: date ==> int
+         , "dayOfWeek" -: date ==> day
+         , "toTime"    -: date ==> time
+         ] ++ days ++ months)
+
 --------  Math and Binops  --------
 
 binop t = t ==> t ==> t
@@ -213,7 +249,6 @@
                         , Context ("`" ++ name ++ "'") $ VarT 1 :<: s2
                         ] (t (VarT 0) (VarT 1)))
 numScheme t name = scheme1 number t name
-timeScheme name t = scheme1 time t name
 twoNums f name = scheme2 number number f name
 
 math =
@@ -377,5 +412,5 @@
     where hs = concat [ funcs, lists, signals, math, bools, textAttrs
                       , graphicsElement, graphicsColor
                       , concreteSignals, javascript, json, maybeFuncs
-                      , http, dictionary, sets, automaton
+                      , http, dictionary, sets, automaton, times, dates
                       ]
diff --git a/src/Types/Solver.hs b/src/Types/Solver.hs
new file mode 100644
--- /dev/null
+++ b/src/Types/Solver.hs
@@ -0,0 +1,157 @@
+
+module Types.Solver (solver) where
+
+import Control.Arrow (second)
+import Control.Monad (liftM)
+import Data.Either (lefts,rights)
+import Data.List (foldl')
+import Data.Maybe (isJust)
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import Guid
+import Types.Types
+import Types.Constrain
+import Types.Substitutions
+
+
+eq ctx t1 t2 = Context ctx (t1 :=: t2)
+
+isSolved ss (Context _ (t1 :=: t2)) = t1 == t2
+isSolved ss (Context _ (x :<<: _)) = isJust (lookup x ss)
+isSolved ss c = False
+
+crush (Forall xs cs t) =
+    do subs <- solver cs Map.empty
+       return $ do ss' <- subs
+                   let ss  = Map.toList ss'
+                       cs' = filter (not . isSolved ss) (subst ss cs)
+                   return $ Forall xs cs' (subst ss t)
+
+schemeSubHelp ctx x s t1 rltn t2 = do
+  (t1',cs1) <- sub t1
+  (t2',cs2) <- sub t2
+  return (Context ctx (rltn t1' t2') : cs1 ++ cs2)
+      where sub t | not (occurs x t) = return (t, [])
+                  | otherwise = do (st, cs) <- concretize s
+                                   return (subst [(x,st)] t, cs)
+
+schemeSub x s c = do s' <- crush s
+                     case s' of
+                       Right s'' -> Right `liftM` schemeSub' x s'' c
+                       Left err  -> return $ Left err
+
+schemeSub' x s (Context ctx (t1 :=: t2)) = schemeSubHelp ctx x s t1 (:=:) t2
+schemeSub' x s (Context ctx (t1 :<: t2)) = schemeSubHelp ctx x s t1 (:<:) t2
+schemeSub' x s c@(Context ctx (y :<<: Forall cxs ccs ctipe))
+    | not (occurs x c) = return [c]
+    | otherwise =
+        do Forall xs cs tipe <- rescheme s
+           let ss = [(x,tipe)]
+               constraints = subst ss (cs ++ ccs)
+               c' = y :<<: Forall (cxs ++ xs) constraints (subst ss ctipe)
+           return [ Context ctx c' ]
+
+
+solver :: [Context String Constraint]
+       -> Map.Map X Type
+       -> GuidCounter (Either String (Map.Map X Type))
+solver [] subs = return $ Right subs
+
+--------  Destruct Type-constructors  --------
+
+solver ((Context ctx (t1@(ADT n1 ts1) :=: t2@(ADT n2 ts2))) : cs) subs =
+    if n1 /= n2 then uniError ctx t1 t2 else
+        solver (zipWith (eq ctx) ts1 ts2 ++ cs) subs
+solver ((Context ctx (LambdaT t1 t2 :=: LambdaT t1' t2')) : cs) subs =
+    solver ([ eq ctx t1 t1', eq ctx t2 t2' ] ++ cs) subs
+
+--------  Type-equality  --------
+
+solver (Context ctx (VarT x :=: VarT y) : cs) subs
+    | x == y    = solver cs subs
+    | otherwise =
+        case (Map.lookup x subs, Map.lookup y subs) of
+          (Just (Super xts), Just (Super yts)) ->
+             let ts = Set.intersection xts yts
+                 setXY t = Map.insert x t . Map.insert y t
+             in  case Set.toList ts of
+                   []  -> unionError ctx xts yts
+                   [t] -> let cs1 = subst [(x,t),(y,t)] cs in
+                          cs1 `seq` solver cs1 (setXY t subs)
+                   _   -> solver cs $ setXY (Super ts) subs
+          (Just (Super xts), _) ->
+              let cs2 = subst [(y,VarT x)] cs in
+              solver cs2 $ Map.insert y (VarT x) subs
+          (_, _) ->
+              let cs3 = subst [(x,VarT y)] cs in
+              solver cs3 $ Map.insert x (VarT y) subs
+solver (Context ctx (VarT x :=: t) : cs) subs = do
+  if x `occurs` t then occursError ctx (VarT x) t else
+      (case Map.lookup x subs of
+         Nothing -> let cs4 = subst [(x,t)] cs in
+                    solver cs4 . Map.map (subst [(x,t)]) $ Map.insert x t subs
+         Just (Super ts) ->
+             let ts' = Set.intersection ts (Set.singleton t) in
+             case Set.toList ts' of
+               []   -> solver (Context ctx (t :<: Super ts) : cs) subs
+               [t'] -> let cs5 = subst [(x,t)] cs in
+                       solver cs5 $ Map.insert x t' subs
+               _    -> solver cs $ Map.insert x (Super ts') subs
+         Just t' -> solver (Context ctx (t' :=: t) : cs) subs
+      )
+solver ((Context ctx (t :=: VarT x)) : cs) subs =
+    solver ((Context ctx (VarT x :=: t)) : cs) subs
+solver ((Context ctx (t1 :=: t2)) : cs) subs
+    | t1 == t2  = solver cs subs
+    | otherwise = uniError ctx t1 t2
+
+
+--------  subtypes  --------
+
+solver (Context ctx (VarT x :<: Super ts) : cs) subs =
+    case Map.lookup x subs of
+      Nothing -> solver cs $ Map.insert x (Super ts) subs
+      Just (Super ts') ->
+          case Set.toList $ Set.intersection ts ts' of
+            []   -> unionError ctx ts ts'
+            [t]  -> solver (subst [(x,t)] cs) $ Map.insert x t subs
+            ts'' -> solver cs $ Map.insert x (Super $ Set.fromList ts'') subs
+
+solver (Context ctx (ADT "List" [t] :<: Super ts) : cs) subs
+    | any f (Set.toList ts) = solver cs subs
+    | otherwise = subtypeError ctx (ADT "List" [t]) (Super ts)
+        where f (ADT "List" [VarT _]) = True
+              f (ADT "List" [t']) = t == t'
+              f _ = False
+
+solver (Context ctx (t :<: Super ts) : cs) subs
+    | Set.member t ts = solver cs subs
+    | otherwise = subtypeError ctx t (Super ts)
+
+solver (Context ctx (x :<<: s) : cs) subs
+    | any (occurs x) cs =
+        do css <- mapM (schemeSub x s) cs
+           case lefts css of
+             err : _ -> return $ Left err
+             [] -> solver (concat (rights css)) subs
+    | otherwise =
+        do (t,cs7) <- concretize s
+           let cs'' = (cs ++ Context ctx (VarT x :=: t) : map (extendCtx ctx) cs7)
+           solver cs'' subs
+
+occursError ctx t1 t2 =
+    return . Left $ "Type error: Occurs check: cannot construct the infinite type: " ++ show t1 ++
+                    " = " ++ show t2 ++
+                    " in context " ++ ctx
+uniError ctx t1 t2 =
+    return . Left $ "Type error: " ++ show t1 ++
+                    " is not equal to " ++ show t2 ++
+                    " in context " ++ ctx
+unionError ctx ts ts' =
+    return . Left $ concat [ "Type error: There are no types in both "
+                           , show (Super ts), " and ", show (Super ts')
+                           , " in context ", ctx ]
+subtypeError ctx t s =
+    return . Left $ concat [ "Type error: ", show t, " is not a ", show s
+                           , " in context ", ctx ]
+
diff --git a/src/Types/Substitutions.hs b/src/Types/Substitutions.hs
--- a/src/Types/Substitutions.hs
+++ b/src/Types/Substitutions.hs
@@ -1,10 +1,6 @@
 
-module Types.Substitutions (cSub
-                           ,tSub
-                           ,cSubNoContext
-                           ,hasVarC
-                           ,freeVars
-                           ,schemeSub
+module Types.Substitutions (subst
+                           ,occurs
                            ,concretize
                            ,rescheme
                            ,generalize) where
@@ -14,108 +10,85 @@
 import Data.List (foldl')
 import qualified Data.Set as Set
 import Guid
-import Types
+import Types.Types
 
-force x = x `deepseq` x
-a ++++ b = foldl' (\tl hd -> hd : tl) b a
-map' f xs = map (\x -> let v = f x in v `seq` v) xs
 
-instance (NFData a) => NFData (Context c a) where
-  rnf (Context _ a) = a `deepseq` ()
+class Subst a where
+  subst :: [(X,Type)] -> a -> a
 
-instance NFData Scheme where
-  rnf (Forall vs cs t) = vs `deepseq` cs `deepseq` t `deepseq` ()
+instance Subst Type where
+  subst ss (VarT x) = case lookup x ss of
+                        Nothing        -> VarT x
+                        Just (Super _) -> VarT x
+                        Just t         -> t
+  subst ss (LambdaT t1 t2) = LambdaT (subst ss t1) (subst ss t2)
+  subst ss (ADT name ts) = ADT name (subst ss ts)
+  subst ss (Super ts) = Super ts
 
-instance NFData Constraint where
-  rnf (t1 :=: t2) = t1 `deepseq` t2 `deepseq` ()
-  rnf (t1 :<: t2) = t1 `deepseq` t2 `deepseq` ()
-  rnf (t :<<: s)  = t `deepseq` s `deepseq` ()
+instance Subst Scheme where
+  subst ss (Forall vs cs t) = Forall vs (subst ss cs) (subst ss t)
 
-instance NFData Type where
-  rnf (LambdaT t1 t2) = t1 `deepseq` t2 `deepseq` ()
-  rnf (ADT _ ts) =  foldl' (\acc x -> x `deepseq` acc) () ts
-  rnf t = t `seq` ()
+instance Subst Constraint where
+  subst ss (t1 :=: t2) = subst ss t1 :=: subst ss t2
+  subst ss (t :<: super) = subst ss t :<: super
+  subst ss (x :<<: poly) = x :<<: subst ss poly
 
-tSub k v t@(VarT x) = if k == x then v else t
-tSub k v (LambdaT t1 t2) = tSub k v t1 `seq` tSub k v t2 `seq` LambdaT (tSub k v t1) (tSub k v t2)
-tSub k v (ADT name ts) = map' (tSub k v) ts `seq` ADT name (map' (tSub k v) ts)
-tSub k v (Super ts) = Super ts
+instance Subst a => Subst (Context c a) where
+  subst ss (Context ctx c) = Context ctx (subst ss c)
 
-schemeSubHelp k s c t1 t2 relation = do
-  (t1',cs1) <- f t1
-  (t2',cs2) <- f t2
-  return $ Context c (relation t1' t2') : cs1 ++++ cs2
-    where f t | hasVar k t = do (v, cs) <- concretize s; return (tSub k v t, cs)
-              | otherwise  = return (t, [])
+instance Subst a => Subst [a] where
+  subst ss as = map (subst ss) as
 
-schemeSub k s (Context ctx (t1 :=: t2)) = t1 `seq` t2 `seq` schemeSubHelp k s ctx t1 t2 (:=:)
-schemeSub k s (Context ctx (t1 :<: t2)) = t1 `seq` t2 `seq` schemeSubHelp k s ctx t1 t2 (:<:)
-schemeSub k s c@(Context ctx (x :<<: Forall cxs ccs ctipe)) =
-    if not $ hasVarC k c then return [c]
-    else do
-      Forall xs cs tipe <- rescheme s
-      let constraints = map' (cSub k tipe) $ cs ++ ccs
-      let c' = x :<<: Forall (cxs ++ xs) constraints (tSub k tipe ctipe)
-      return [ Context ctx c' ]
 
-hasVar v (VarT x) = v == x
-hasVar v (LambdaT t1 t2) = force (hasVar v t1 || hasVar v t2)
-hasVar v (ADT _ ts) = force $ any (hasVar v) ts
-hasVar v (Super _ ) = False
+class FreeVars a where
+  freeVars :: a -> [X]
 
-cSub k v (Context ctx c) = out `deepseq` out
-    where out = Context ctx (cSubNoContext' k v c)
+instance FreeVars Type where
+  freeVars (VarT v) = [v]
+  freeVars (LambdaT t1 t2) = freeVars t1 ++ freeVars t2
+  freeVars (ADT _ ts) = concatMap freeVars ts
+  freeVars (Super _ ) = [] 
 
-cSubNoContext k v c = c' `deepseq` c'
-    where c' = cSubNoContext' k v c
+instance FreeVars Constraint where
+  freeVars (t1 :=: t2) = freeVars t1 ++ freeVars t2
+  freeVars (t1 :<: t2) = freeVars t1 ++ freeVars t2
+  freeVars (x :<<: Forall xs cs t) = filter (`notElem` xs) frees
+      where frees = concatMap freeVars cs ++ freeVars t
 
-cSubNoContext' k v (t1 :=: t2) = let { t1' = tSub k v $! t1 ; t2' = tSub k v $! t2 } in
-                                 t1' `seq` t2' `seq` t1' :=: t2'
-cSubNoContext' k v (t :<: super) = let t' = tSub k v t in t' `seq` t' :<: super
-cSubNoContext' k v (x :<<: poly@(Forall vs cs tipe)) = (x :<<: poly')
-    where poly' | k `elem` vs = poly
-                | otherwise = let tipe' = tSub k v tipe in
-                              tipe' `deepseq` Forall vs (map' (cSub k v) cs) tipe'
+instance FreeVars a => FreeVars (Context c a) where
+  freeVars (Context _ c) = freeVars c    
 
-concretize (Forall xs cs t) = do
-  pairs <- zip xs `liftM` mapM (const guid) xs
-  let tipe = foldl' (\t' (k,v) -> tSub k (VarT v) $! t') t pairs
-  let f c = foldl' (\c (k,v) -> cSub k (VarT v) $! c) c $! pairs
-  let cs' = f `seq` map' f cs
-  tipe `deepseq` cs' `deepseq` return (tipe, cs')
 
-rescheme :: Scheme -> GuidCounter Scheme
-rescheme (Forall xs cs t) = do
-  pairs <- zip xs `liftM` mapM (const guid) xs
-  let tipe = foldl' (\t' (k,v) -> tSub k (VarT v) $! t') t pairs
-  let fs = map (\(k,v) -> cSub k (VarT v)) pairs
-  let cs' = map (\c -> foldl' (\c f -> f $! c) c fs) cs
-  tipe `deepseq` cs' `deepseq` (return $ Forall (map' snd pairs) cs' tipe)
-
-freeVars t = let fs = freeVars' t in fs `deepseq` fs
-
-freeVars' (VarT v) = [v]
-freeVars' (LambdaT t1 t2) = freeVars' t1 ++++ freeVars' t2
-freeVars' (ADT _ ts) = concatMap freeVars' ts
-freeVars' (Super _ ) = []
+class Occurs a where
+  occurs :: X -> a -> Bool
 
-cFreeVars c = let fs = cFreeVars' c in fs `deepseq` fs
+instance Occurs Type where
+  occurs v (VarT x) = v == x
+  occurs v (LambdaT t1 t2) = occurs v t1 || occurs v t2
+  occurs v (ADT _ ts) = any (occurs v) ts
+  occurs v (Super _ ) = False
 
-cFreeVars' (t1 :=: t2) = freeVars' t1 ++++ freeVars' t2
-cFreeVars' (t1 :<: t2) = freeVars' t1 ++++ freeVars' t2
-cFreeVars' (x :<<: Forall xs cs t) = filter (`notElem` xs) frees
-    where frees = concatMap (\(Context _ c) -> cFreeVars' c) cs ++++ freeVars' t
+instance Occurs Constraint where
+  occurs x (t1 :=: t2) = occurs x t1 || occurs x t2
+  occurs x (t1 :<: t2) = occurs x t1 || occurs x t2
+  occurs x (y :<<: Forall xs cs t) = x == y || occurs x t || inCs
+      where inCs = x `notElem` xs && any (occurs x) cs
 
+instance Occurs a => Occurs (Context c a) where
+  occurs x (Context _ c) = occurs x c
 
-hasVarC x (Context _ (t1 :=: t2)) = hasVar x t1 || hasVar x t2
-hasVarC x (Context _ (t1 :<: t2)) = hasVar x t1 || hasVar x t2
-hasVarC x (Context _ (y :<<: Forall xs cs t)) = x == y || hasVar x t || inCs
-    where inCs = x `notElem` xs && any (hasVarC x) cs
+concretize :: Scheme -> GuidCounter (Type, [Context String Constraint])
+concretize (Forall xs cs t) = do
+  ss <- zip xs `liftM` mapM (\_ -> liftM VarT guid) xs
+  return (subst ss t, subst ss cs)
 
-decontext (Context _ c) = c
+rescheme :: Scheme -> GuidCounter Scheme
+rescheme (Forall xs cs t) = do
+  xs' <- mapM (const guid) xs
+  let ss = zip xs (map VarT xs')
+  return $ Forall xs' (subst ss cs) (subst ss t)
 
 generalize :: [X] -> Scheme -> GuidCounter Scheme
 generalize exceptions (Forall xs cs t) = rescheme (Forall (xs ++ frees) cs t)
-    where allFrees = Set.fromList $ freeVars t ++ concatMap (cFreeVars . decontext) cs
+    where allFrees = Set.fromList $ freeVars t ++ concatMap freeVars cs
           frees = Set.toList $ Set.difference allFrees (Set.fromList exceptions)
-
diff --git a/src/Types/Types.hs b/src/Types/Types.hs
--- a/src/Types/Types.hs
+++ b/src/Types/Types.hs
@@ -1,105 +1,107 @@
-
-module Types where
-
-import Data.Char (isDigit)
-import Data.List (intercalate,isPrefixOf)
-import qualified Data.Set as Set
-
-type X = Int
-
-data Type = LambdaT Type Type
-          | VarT X
-          | ADT String [Type]
-          | Super (Set.Set Type)
-            deriving (Eq, Ord)
-
-data Scheme = Forall [X] [Context String Constraint] Type deriving (Eq, Ord)
-
-data Constraint = Type :=: Type
-                | Type :<: Type
-                | X :<<: Scheme
-                  deriving (Eq, Ord, Show)
-
-data Context c v = Context c v deriving (Eq, Show)
-
-ctx c = Context ("`" ++ show c ++ "'")
-extendCtx ctx2 (Context ctx1 c) = Context (ctx1 ++ " in " ++ ctx2) c
-
-instance (Ord a, Eq c) => Ord (Context c a) where
-    compare (Context _ x) (Context _ y) = compare x y
-
-
-tipe t = ADT t []
-
-
-int = tipe "Int"
-float = tipe "Float"
-number = Super (Set.fromList [ int, float ])
-
-char = tipe "Char"
-bool = tipe "Bool"
-
-string = listOf char -- tipe "String"
-text  = tipe "Text"
-
-time = Super (Set.fromList [ int, float ])
-
-element   = tipe "Element"
-direction = tipe "Direction"
-form  = tipe "Form"
-line  = tipe "Line"
-shape = tipe "Shape"
-color = tipe "Color"
-position = tipe "Position"
-location = tipe "Location"
-
-listOf t   = ADT "List" [t]
-signalOf t = ADT "Signal" [t]
-tupleOf ts = ADT ("Tuple" ++ show (length ts)) ts
-maybeOf t  = ADT "Maybe" [t]
-pairOf t = tupleOf [t,t]
-point = pairOf int
-appendable t = Super (Set.fromList [ string, text, listOf t ])
-comparable = Super (Set.fromList [ int, float, char, string ])
-transformable = Super (Set.fromList [ shape, line ])
-
-jsBool     = tipe "JSBool"
-jsNumber   = tipe "JSNumber"
-jsString   = tipe "JSString"
-jsElement  = tipe "JSElement"
-jsArray t  = ADT "JSArray" [t]
-jsTuple ts = ADT ("JSTuple" ++ show (length ts)) ts
-jsonValue = tipe "JsonValue"
-jsonObject = tipe "JsonObject"
-
-infixr ==>
-t1 ==> t2 = LambdaT t1 t2
-
-infix 8 -:
-name -: tipe = (,) name $ Forall [] [] tipe
-
-hasType t = map (-: t)
-
-parens = ("("++) . (++")")
-
-instance Show Type where
-  show t =
-      case t of
-        { LambdaT t1@(LambdaT _ _) t2 -> parens (show t1) ++ " -> " ++ show t2
-        ; LambdaT t1 t2 -> show t1 ++ " -> " ++ show t2
-        ; VarT x -> 't' : show x
-        ; ADT "List" [ADT "Char" []] -> "String"
-        ; ADT "List" [tipe] -> "[" ++ show tipe ++ "]"
-        ; ADT name cs ->
-            if isTupleString name
-                then parens . intercalate "," $ map show cs
-                else case cs of [] -> name
-                                _ -> parens $ name ++ " " ++ unwords (map show cs)
-        ; Super ts -> "{" ++ (intercalate "," . map show $ Set.toList ts) ++ "}"
-        }
-
-instance Show Scheme where
-  show (Forall xs cs t) = "Forall " ++ show xs ++ cs' ++ "\n  " ++ show t
-      where cs' = concatMap (concatMap ("\n  "++) . lines . show) cs
-
+
+module Types.Types where
+
+import Data.Char (isDigit)
+import Data.List (intercalate,isPrefixOf)
+import qualified Data.Set as Set
+
+type X = Int
+
+data Type = LambdaT Type Type
+          | VarT X
+          | ADT String [Type]
+          | Super (Set.Set Type)
+            deriving (Eq, Ord)
+
+data Scheme = Forall [X] [Context String Constraint] Type deriving (Eq, Ord)
+
+data Constraint = Type :=: Type
+                | Type :<: Type
+                | X :<<: Scheme
+                  deriving (Eq, Ord, Show)
+
+data Context c v = Context c v deriving (Eq, Show)
+
+ctx c = Context ("`" ++ show c ++ "'")
+extendCtx ctx2 (Context ctx1 c) = Context (ctx1 ++ " in " ++ ctx2) c
+
+instance (Ord a, Eq c) => Ord (Context c a) where
+    compare (Context _ x) (Context _ y) = compare x y
+
+
+tipe t = ADT t []
+
+
+int = tipe "Int"
+float = tipe "Float"
+number = Super (Set.fromList [ int, float ])
+
+char = tipe "Char"
+bool = tipe "Bool"
+
+string = listOf char -- tipe "String"
+text  = tipe "Text"
+
+time = float --tipe "Time"
+date = tipe "Date"
+month = tipe "Month"
+day = tipe "Day"
+
+element   = tipe "Element"
+direction = tipe "Direction"
+form  = tipe "Form"
+line  = tipe "Line"
+shape = tipe "Shape"
+color = tipe "Color"
+position = tipe "Position"
+location = tipe "Location"
+
+listOf t   = ADT "List" [t]
+signalOf t = ADT "Signal" [t]
+tupleOf ts = ADT ("Tuple" ++ show (length ts)) ts
+maybeOf t  = ADT "Maybe" [t]
+pairOf t = tupleOf [t,t]
+point = pairOf int
+appendable t = Super (Set.fromList [ string, text, listOf t ])
+comparable = Super (Set.fromList [ int, float, char, string, time, date ])
+
+jsBool     = tipe "JSBool"
+jsNumber   = tipe "JSNumber"
+jsString   = tipe "JSString"
+jsElement  = tipe "JSElement"
+jsArray t  = ADT "JSArray" [t]
+jsTuple ts = ADT ("JSTuple" ++ show (length ts)) ts
+jsonValue = tipe "JsonValue"
+jsonObject = tipe "JsonObject"
+
+infixr ==>
+t1 ==> t2 = LambdaT t1 t2
+
+infix 8 -:
+name -: tipe = (,) name $ Forall [] [] tipe
+
+hasType t = map (-: t)
+
+parens = ("("++) . (++")")
+
+instance Show Type where
+  show t =
+      case t of
+        { LambdaT t1@(LambdaT _ _) t2 -> parens (show t1) ++ " -> " ++ show t2
+        ; LambdaT t1 t2 -> show t1 ++ " -> " ++ show t2
+        ; VarT x -> 't' : show x
+        ; ADT "List" [ADT "Char" []] -> "String"
+        ; ADT "List" [tipe] -> "[" ++ show tipe ++ "]"
+        ; ADT name cs ->
+            if isTupleString name
+                then parens . intercalate "," $ map show cs
+                else case cs of [] -> name
+                                _ -> parens $ name ++ " " ++ unwords (map show cs)
+        ; Super ts -> "{" ++ (intercalate "," . map show $ Set.toList ts) ++ "}"
+        }
+
+instance Show Scheme where
+  show (Forall xs cs t) = "Forall " ++ show xs ++ cs' ++ "\n  " ++ show t
+      where cs' = concatMap (concatMap ("\n  "++) . lines . show) cs
+
 isTupleString str = "Tuple" `isPrefixOf` str && all isDigit (drop 5 str)
diff --git a/src/Types/Unify.hs b/src/Types/Unify.hs
--- a/src/Types/Unify.hs
+++ b/src/Types/Unify.hs
@@ -1,20 +1,12 @@
 
 module Types.Unify (unify) where
 
-import Control.Arrow (second)
 import Control.Monad (liftM)
-import Data.List (foldl')
-import qualified Data.Set as Set
 import qualified Data.Map as Map
+
 import Guid
-import Types
 import Types.Constrain
-import Types.Substitutions
-
-import Control.DeepSeq (deepseq)
---import System.IO.Unsafe
-
-prints xs v = v --} unsafePerformIO (putStrLn "----------" >> mapM print xs) `seq` v
+import Types.Solver
 
 unify hints modul = run $ do
   constraints <- constrain hints modul
@@ -24,106 +16,3 @@
         do subs <- solver cs Map.empty
            return ((,) escapees `liftM` subs)
 
-eq ctx t1 t2 = Context ctx (t1 :=: t2)
-
-
-solver [] subs = prints (Map.toList subs) $ return $ Right subs
-
---------  Destruct Type-constructors  --------
-
-solver ((Context ctx (t1@(ADT n1 ts1) :=: t2@(ADT n2 ts2))) : cs) subs =
-    if n1 /= n2 then uniError ctx t1 t2 else
-        solver (zipWith (eq ctx) ts1 ts2 ++ cs) subs
-solver ((Context ctx (LambdaT t1 t2 :=: LambdaT t1' t2')) : cs) subs =
-    solver ([ eq ctx t1 t1', eq ctx t2 t2' ] ++ cs) subs
-
---------  Type-equality  --------
-
-solver (Context ctx (VarT x :=: VarT y) : cs) subs
-    | x == y    = solver cs subs
-    | otherwise =
-        case (Map.lookup x subs, Map.lookup y subs) of
-          (Just (Super xts), Just (Super yts)) ->
-             let ts = Set.intersection xts yts
-                 setXY t = Map.insert x t . Map.insert y t
-             in  case Set.toList ts of
-                   []  -> unionError ctx xts yts
-                   [t] -> let cs1 = map (\c -> cSub y t c `seq` cSub x t (cSub y t c)) cs in
-                          cs1 `seq` solver cs1 (setXY t subs)
-                   _   -> solver cs $ setXY (Super ts) subs
-          (Just (Super xts), _) ->
-              let cs2 = map (cSub y (VarT x)) cs in
-              cs2 `seq` solver cs2 $ Map.insert y (VarT x) subs
-          (_, _) ->
-              let cs3 = map (cSub x (VarT y)) cs in
-              cs3 `deepseq` solver cs3 $ Map.insert x (VarT y) subs
-solver (Context ctx (VarT x :=: t) : cs) subs = do
-  if x `occursIn` t then occursError ctx (VarT x) t else
-      (case Map.lookup x subs of
-         Nothing -> let cs4 = map (cSub x t) cs in
-                    cs4 `deepseq` (solver cs4 . Map.map (tSub x t) $ Map.insert x t subs)
-         Just (Super ts) ->
-             let ts' = Set.intersection ts (Set.singleton t) in
-             case Set.toList ts' of
-               []   -> solver (Context ctx (t :<: Super ts) : cs) subs
-               [t'] -> let cs5 = map (cSub x t) cs in
-                       cs5 `seq` solver cs5 $ Map.insert x t' subs
-               _    -> solver cs $ Map.insert x (Super ts') subs
-         Just t' -> solver (Context ctx (t' :=: t) : cs) subs
-      )
-solver ((Context ctx (t :=: VarT x)) : cs) subs =
-    solver ((Context ctx (VarT x :=: t)) : cs) subs
-solver ((Context ctx (t1 :=: t2)) : cs) subs
-    | t1 == t2  = solver cs subs
-    | otherwise = uniError ctx t1 t2
-
-
---------  subtypes  --------
-
-solver (Context ctx (VarT x :<: Super ts) : cs) subs =
-    case Map.lookup x subs of
-      Nothing -> solver cs $ Map.insert x (Super ts) subs
-      Just (Super ts') ->
-          case Set.toList $ Set.intersection ts ts' of
-            []   -> unionError ctx ts ts'
-            [t]  -> solver (map (cSub x t) cs) $ Map.insert x t subs
-            ts'' -> solver cs $ Map.insert x (Super $ Set.fromList ts'') subs
-
-solver (Context ctx (ADT "List" [t] :<: Super ts) : cs) subs
-    | any f (Set.toList ts) = solver cs subs
-    | otherwise = subtypeError ctx (ADT "List" [t]) (Super ts)
-        where f (ADT "List" [VarT _]) = True
-              f (ADT "List" [t']) = t == t'
-              f _ = False
-
-solver (Context ctx (t :<: Super ts) : cs) subs
-    | Set.member t ts = solver cs subs
-    | otherwise = subtypeError ctx t (Super ts)
-
-solver (Context ctx (x :<<: s) : cs) subs
-    | any (hasVarC x) cs =
-        do cs6 <- concat `liftM` mapM (schemeSub x s) cs
-           solver cs6 subs
-    | otherwise =
-        do (t,cs7) <- concretize s
-           let cs'' = (cs ++ Context ctx (VarT x :=: t) : map (extendCtx ctx) cs7)
-           solver cs'' subs
-
-
-occursError ctx t1 t2 =
-    return . Left $ "Type error: Occurs check: cannot construct the infinite type: " ++ show t1 ++
-                    " = " ++ show t2 ++
-                    " in context " ++ ctx
-uniError ctx t1 t2 =
-    return . Left $ "Type error: " ++ show t1 ++
-                    " is not equal to " ++ show t2 ++
-                    " in context " ++ ctx
-unionError ctx ts ts' =
-    return . Left $ concat [ "Type error: There are no types in both "
-                           , show (Super ts), " and ", show (Super ts')
-                           , " in context ", ctx ]
-subtypeError ctx t s =
-    return . Left $ concat [ "Type error: ", show t, " is not a ", show s
-                           , " in context ", ctx ]
-
-occursIn x t = x `elem` freeVars t
