diff --git a/Elm.cabal b/Elm.cabal
--- a/Elm.cabal
+++ b/Elm.cabal
@@ -1,11 +1,12 @@
 
 Name:                Elm
-Version:             0.1.1.7
-Synopsis:            The Elm compiler and server.
+Version:             0.1.2
+Synopsis:            The Elm language module.
 Description:         Elm aims to make client-side web-development more pleasant.
                      It is a statically/strongly typed, functional reactive
                      language to HTML, CSS, and JS. This package provides a
-                     compiler and server for Elm.
+                     library for Elm compilation in Haskell and a compiler
+                     executable.
 
 Homepage:            http://elm-lang.org
 
@@ -20,53 +21,81 @@
 
 Build-type:          Simple
 
-Extra-source-files:  README.md
-Cabal-version:       >=1.6
+--Extra-source-files:  README.md
+Cabal-version:       >=1.8
 
 source-repository head
   type:     git
   location: git://github.com/evancz/Elm.git
 
-Executable elm
-  -- .hs or .lhs file containing the Main module.
-  Main-is:             Compiler.hs
-  Hs-Source-Dirs:      src, src/Parse, src/Types, src/Language
-  other-modules:       Ast, CompileToJS, GenerateHtml, Guid, Initialize,
-                       Rename, Language.Elm, Binop, Combinators, Lexer,
-                       ParsePatterns, Parser, ParserLib, ParseTypes, Tokens,
-                       Types, Constrain, Hints, Types, Unify, ExtractNoscript
-  
-  -- Packages needed in order to build this package.
-  ghc-options:	       -O3
-  Build-depends:       base >=4.2 && <5, containers >= 0.3,
-                       transformers >= 0.2, mtl >= 2, parsec >= 3.1.1,
-                       blaze-html == 0.5.0.*, blaze-markup == 0.5.1.*,
-                       deepseq
-  
-  -- Modules not exported by this package.
-  -- Other-modules:       
-  
-  -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.
-  -- Build-tools:         
+Library
+  exposed-modules:     Language.Elm,
+                       Language.Elm.Quasi
+  ghc-options:         -O2
+  Hs-Source-Dirs:      src, src/Parse, src/Types
+  other-modules:       Ast,
+                       CompileToJS,
+                       ExtractNoscript,
+                       GenerateHtml,
+                       Guid,
+                       Initialize,
+                       Rename,
+                       Binop,
+                       Combinators,
+                       Lexer,
+                       ParsePatterns,
+                       Parser,
+                       ParserLib,
+                       ParseTypes,
+                       Tokens,
+                       Types,
+                       Constrain,
+                       Hints,
+                       Types,
+                       Unify
 
+  Build-depends:       base >=4.2 && <5,
+                       containers >= 0.3,
+                       transformers >= 0.2,
+                       mtl >= 2,
+                       parsec >= 3.1.1,
+                       blaze-html == 0.5.0.*,
+                       blaze-markup == 0.5.1.*,
+                       deepseq,
+                       text,
+                       template-haskell,
+                       shakespeare
 
-Executable elm-server
-  Main-is:             Server.hs
+Executable elm
+  Main-is:             Compiler.hs
+  ghc-options:         -O2
   Hs-Source-Dirs:      src, src/Parse, src/Types
-  other-modules:       Ast, CompileToJS, GenerateHtml, Guid, Initialize,
-                       Rename, Language.Elm, Binop, Combinators, Lexer,
-                       ParsePatterns, Parser, ParserLib, ParseTypes, Tokens,
-                       Types, Constrain, Hints, Types, Unify, ExtractNoscript
-  ghc-options:	       -O3
-  Build-depends:       base >=4.2 && <5, containers >= 0.3, transformers >= 0.2,
-                       mtl >= 2, parsec >= 3.1.1, blaze-html == 0.5.0.*,
-                       HTTP >= 4000, happstack-server == 7.0.2,
-                       deepseq
+  other-modules:       Ast,
+                       CompileToJS,
+                       ExtractNoscript,
+                       GenerateHtml,
+                       Guid,
+                       Initialize,
+                       Rename,
+                       Binop,
+                       Combinators,
+                       Lexer,
+                       ParsePatterns,
+                       Parser,
+                       ParserLib,
+                       ParseTypes,
+                       Tokens,
+                       Types,
+                       Constrain,
+                       Hints,
+                       Types,
+                       Unify
 
-Library
-  exposed-modules:     Language.Elm
-  Hs-Source-Dirs:      src, src/Parse, src/Types
-  other-modules:       Ast, CompileToJS, GenerateHtml, Guid, Initialize,
-                       Rename, Binop, Combinators, Lexer,
-                       ParsePatterns, Parser, ParserLib, ParseTypes, Tokens,
-                       Types, Constrain, Hints, Types, Unify, ExtractNoscript
+  Build-depends:       base >=4.2 && <5,
+                       containers >= 0.3,
+                       transformers >= 0.2,
+                       mtl >= 2,
+                       parsec >= 3.1.1,
+                       blaze-html == 0.5.0.*,
+                       blaze-markup == 0.5.1.*,
+                       deepseq
diff --git a/README.md b/README.md
deleted file mode 100644
--- a/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-Elm
-===
-
-This is the Elm compiler and server, allowing you to develop Elm applications that run in any modern browser.
-
-Installation Process
---------------------
-
-Download the [Haskell Platform](http://hackage.haskell.org/platform/). This will give you access to the Haskell compiler (needed to build Elm) and Haskell's package distribution system (to make installation of Elm easier). Once installed (even if it already was), you must update your listing of Haskell packages with:
-
-    cabal update
-
-This will ensure that the elm package is available. Then install Elm with:
-
-    cabal install elm
-
-Assuming everything goes correctly (potential problems are discussed later), this will build two executables on your machine:
-
-* `elm` is a standard compiler that takes `.elm` files and produces `.html` files. You can then use these HTML files with your favorite web-framework.
-
-* `elm-server` is both a compiler and server, allowing you to develop without designing and setting up a server yourself. Running `elm-server` starts a server in the current directory. It will compile and serve any `.elm` files in the current directory and its sub-directories. This is how I prefer to develop Elm programs.
-
-To use these executables you need to add a new directory to your PATH. For me, the executables were placed in /home/evan/.cabal/bin which I appended to the end of my PATH variable in my .bashrc file. Cabal should tell you where your executables are located, so you can make a similar addition (see this tutorial if you are new to changing your PATH in [Unix/Linux](http://www.cyberciti.biz/faq/unix-linux-adding-path/)).
-
-That is almost everything. Now, we will create a simple Elm project. The following commands will set-up a very basic project and start the Elm server.
-
-    mkdir helloElm
-    cd helloElm
-    wget https://raw.github.com/evancz/Elm/master/elm-mini.js
-    echo main = lift asText Mouse.position > main.elm
-    elm-server
-
-The first two commands create a new directory and navigate into it. Then next command (`wget`) downloads the [elm-mini.js](https://raw.github.com/evancz/Elm/master/elm-mini.js) file which is the Elm runtime system and must be in the root directory of your Elm project. If you do not have wget, just follow [this link](https://raw.github.com/evancz/Elm/master/elm-mini.js) and download it directly. The `echo` command places a simple program into `main.elm`. The final command starts the Elm server at [localhost](http://localhost:8000/), allowing you to navigate to `main.elm` and see your first program in action.
-
-
-Potential problems and their solutions:
----------------------------------------
-
-* Install errors having to do with `happstack-server-7.0.2`. This version of `happstack-server` has stricter dependency restrictions that conflict with other libraries required by Elm. Try installing with an earlier version of `happstack-server` with the following command: `cabal install elm --constrain="happstack-server<7.0.2"`
-* When installing on Debian, `blaze-html-0.4.3.2` fails to compile. You must install `blaze-html-0.4.3.1` instead.
-* Elm does not appear to work with the latest versions of `containers` (i.e. 0.4.2.*). I know it works with earlier versions of containers, so to avoid this problem, you can try: `cabal install elm --constrain="containers==0.4.1.0" --force-reinstall`
-* On Windows, HAppStack has trouble installing because of issues with the "network" package. I struggled with this problem on Windows 7 until I found the suggestion at the bottom of [this page](http://hackage.haskell.org/trac/ghc/ticket/5159).
-* Likely more to come...
-
-
-Areas for further work:
------------------------
-
-Error messages need work in general. Syntax and Parsing errors are reported, but the messages are not very helpful. Type errors currently go unreported. I hope to fix this as soon as possible.
-
-If you are interested in making a large contribution, please contact me at `info (at) elm-lang (dot) org` so that we do not duplicate any work!
diff --git a/src/Ast.hs b/src/Ast.hs
--- a/src/Ast.hs
+++ b/src/Ast.hs
@@ -1,39 +1,39 @@
-
-module Ast where
-
-data Pattern = PData String [Pattern] | PVar String | PAnything
-               deriving (Show, Eq)
-
-data Expr = Number Int
-          | Chr Char
-          | Str String
-          | Boolean Bool
-          | Range Expr Expr
-          | Access Expr String
-          | Binop String Expr Expr
-          | Lambda String Expr
-          | App Expr Expr
-          | If Expr Expr Expr
-          | Lift Expr [Expr]
-          | Fold Expr Expr Expr
-          | Async Expr
-          | Input String
-          | Let [(String,Expr)] Expr
-          | Var String
-          | Case Expr [(Pattern,Expr)]
-          | Data String [Expr]
-            deriving (Show, Eq)
-
-cons h t = Data "Cons" [h,t]
-nil      = Data "Nil" []
-list     = foldr cons nil
-tuple es = Data ("Tuple" ++ show (length es)) es
-
-delist (Data "Cons" [h,t]) = h : delist t
-delist _ = []
-
-
-pcons h t = PData "Cons" [h,t]
-pnil      = PData "Nil" []
-plist     = foldr pcons pnil
-ptuple es = PData ("Tuple" ++ show (length es)) es
+
+module Ast where
+
+data Pattern = PData String [Pattern] | PVar String | PAnything
+               deriving (Show, Eq)
+
+data Expr = Number Int
+          | Chr Char
+          | Str String
+          | Boolean Bool
+          | Range Expr Expr
+          | Access Expr String
+          | Binop String Expr Expr
+          | Lambda String Expr
+          | App Expr Expr
+          | If Expr Expr Expr
+          | Lift Expr [Expr]
+          | Fold Expr Expr Expr
+          | Async Expr
+          | Input String
+          | Let [(String,Expr)] Expr
+          | Var String
+          | Case Expr [(Pattern,Expr)]
+          | Data String [Expr]
+            deriving (Show, Eq)
+
+cons h t = Data "Cons" [h,t]
+nil      = Data "Nil" []
+list     = foldr cons nil
+tuple es = Data ("Tuple" ++ show (length es)) es
+
+delist (Data "Cons" [h,t]) = h : delist t
+delist _ = []
+
+
+pcons h t = PData "Cons" [h,t]
+pnil      = PData "Nil" []
+plist     = foldr pcons pnil
+ptuple es = PData ("Tuple" ++ show (length es)) es
diff --git a/src/CompileToJS.hs b/src/CompileToJS.hs
--- a/src/CompileToJS.hs
+++ b/src/CompileToJS.hs
@@ -1,92 +1,92 @@
-
-module CompileToJS (compile, compileToJS) where
-
-import Ast
-import Control.Monad (liftM,(<=<),join)
-import Data.Char (isAlpha)
-import Data.List (intercalate,sortBy)
-import Data.Map (toList)
-
-import Initialize
-
-
-compile = (return . addMain . toJS) <=< initialize
-compileToJS = addMain . either (\err -> "text('"++err++"')") toJS
-addMain body = "function main(){return " ++ body ++ ";}"
-
-parens = ("("++) . (++")")
-braces = ("{"++) . (++"}")
-jsList = ("["++) . (++"]") . intercalate ","
-jsFunc args body = "function(" ++ args ++ "){" ++ body ++ "}"
-assign x e = "var " ++ x ++ "=" ++ e ++ ";"
-ret e = "return "++ e ++";"
-iff a b c = a ++ "?" ++ b ++ ":" ++ c
-
-toJS expr =
-    case expr of
-      Number n -> show n
-      Var x -> x
-      Chr c -> show c
-      Str s -> toJS . list $ map Chr s
-      Boolean b -> if b then "true" else "false"
-      Range lo hi -> jsRange (toJS lo) (toJS hi)
-      Access e lbl -> toJS e ++ "." ++ lbl
-      Binop op e1 e2 -> binop op (toJS e1) (toJS e2)
-      If eb et ef -> parens $ iff (toJS eb) (toJS et) (toJS ef)
-      Lambda v e -> jsFunc v $ ret (toJS e)
-      App (Var "toText") (Str s) -> show s
-      App (Var "link") (Str s) -> "link(" ++ show s ++ ")"
-      App (Var "plainText") (Str s) -> "plainText(" ++ show s ++ ")"
-      App e1 e2 -> toJS e1 ++ parens (toJS e2)
-      Let defs e -> jsLet defs e
-      Case e cases -> jsCase e cases
-      Data name es -> jsList $ show name : map toJS es
-
-jsLet defs e' = jsFunc "" (defs' ++ ret (toJS e')) ++ "()"
-    where defs' = concatMap toDef $ sortBy f defs
-          f a b = compare (isLambda a) (isLambda b)
-          isLambda (_, Lambda _ _) = 1
-          isLambda _ = 0
-          toDef (f, Lambda x e) =
-              "function " ++ f ++ parens x ++ braces (ret $ toJS e) ++ ";"
-          toDef (x, e) = assign x (toJS e)
-
-jsCase e  [c]  = jsMatch c ++ parens (toJS e)
-jsCase e cases = "(function(){" ++
-                 assign "v" (toJS e) ++
-                 assign "c" jsCases  ++
-                 "for(var i=c.length;i--;){" ++
-                 assign "r" "c[i](v)" ++
-                 "if(r!==undefined){return r;}}}())"
-    where jsCases = jsList $ map jsMatch (reverse cases)
-
-jsMatch (p,e) = jsFunc "v" . match p "v" . ret $ toJS e
-match p v hole =
-    case p of
-      PAnything -> hole
-      PVar x -> assign x v ++ hole
-      PData name ps ->
-          "if(" ++ show name ++ "!==" ++ v ++
-          "[0]){return undefined;}else{"++body++"}"
-              where matches = zipWith match ps vs
-                    vs = map (\i -> v++"["++show (i+1)++"]") [0..length ps-1]
-                    body = foldr ($) hole matches
-
-jsNil         = "[\"Nil\"]"
-jsCons  e1 e2 = jsList [ show "Cons", e1, e2 ]
-jsRange e1 e2 = (++"()") . jsFunc "" $
-                assign "lo" e1 ++ assign "hi" e2 ++ assign "lst" jsNil ++
-                "do{" ++ assign "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")
-                    "/=" -> e1 ++ "!==" ++ e2
-                    _ -> e1 ++ (o:p) ++ e2
-
+
+module CompileToJS (compile, compileToJS) where
+
+import Ast
+import Control.Monad (liftM,(<=<),join)
+import Data.Char (isAlpha)
+import Data.List (intercalate,sortBy)
+import Data.Map (toList)
+
+import Initialize
+
+
+compile = (return . addMain . toJS) <=< initialize
+compileToJS = addMain . either (\err -> "text('"++err++"')") toJS
+addMain body = "function main(){return " ++ body ++ ";}"
+
+parens = ("("++) . (++")")
+braces = ("{"++) . (++"}")
+jsList = ("["++) . (++"]") . intercalate ","
+jsFunc args body = "function(" ++ args ++ "){" ++ body ++ "}"
+assign x e = "var " ++ x ++ "=" ++ e ++ ";"
+ret e = "return "++ e ++";"
+iff a b c = a ++ "?" ++ b ++ ":" ++ c
+
+toJS expr =
+    case expr of
+      Number n -> show n
+      Var x -> x
+      Chr c -> show c
+      Str s -> toJS . list $ map Chr s
+      Boolean b -> if b then "true" else "false"
+      Range lo hi -> jsRange (toJS lo) (toJS hi)
+      Access e lbl -> toJS e ++ "." ++ lbl
+      Binop op e1 e2 -> binop op (toJS e1) (toJS e2)
+      If eb et ef -> parens $ iff (toJS eb) (toJS et) (toJS ef)
+      Lambda v e -> jsFunc v $ ret (toJS e)
+      App (Var "toText") (Str s) -> show s
+      App (Var "link") (Str s) -> "link(" ++ show s ++ ")"
+      App (Var "plainText") (Str s) -> "plainText(" ++ show s ++ ")"
+      App e1 e2 -> toJS e1 ++ parens (toJS e2)
+      Let defs e -> jsLet defs e
+      Case e cases -> jsCase e cases
+      Data name es -> jsList $ show name : map toJS es
+
+jsLet defs e' = jsFunc "" (defs' ++ ret (toJS e')) ++ "()"
+    where defs' = concatMap toDef $ sortBy f defs
+          f a b = compare (isLambda a) (isLambda b)
+          isLambda (_, Lambda _ _) = 1
+          isLambda _ = 0
+          toDef (f, Lambda x e) =
+              "function " ++ f ++ parens x ++ braces (ret $ toJS e) ++ ";"
+          toDef (x, e) = assign x (toJS e)
+
+jsCase e  [c]  = jsMatch c ++ parens (toJS e)
+jsCase e cases = "(function(){" ++
+                 assign "v" (toJS e) ++
+                 assign "c" jsCases  ++
+                 "for(var i=c.length;i--;){" ++
+                 assign "r" "c[i](v)" ++
+                 "if(r!==undefined){return r;}}}())"
+    where jsCases = jsList $ map jsMatch (reverse cases)
+
+jsMatch (p,e) = jsFunc "v" . match p "v" . ret $ toJS e
+match p v hole =
+    case p of
+      PAnything -> hole
+      PVar x -> assign x v ++ hole
+      PData name ps ->
+          "if(" ++ show name ++ "!==" ++ v ++
+          "[0]){return undefined;}else{"++body++"}"
+              where matches = zipWith match ps vs
+                    vs = map (\i -> v++"["++show (i+1)++"]") [0..length ps-1]
+                    body = foldr ($) hole matches
+
+jsNil         = "[\"Nil\"]"
+jsCons  e1 e2 = jsList [ show "Cons", e1, e2 ]
+jsRange e1 e2 = (++"()") . jsFunc "" $
+                assign "lo" e1 ++ assign "hi" e2 ++ assign "lst" jsNil ++
+                "do{" ++ assign "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")
+                    "/=" -> e1 ++ "!==" ++ e2
+                    _ -> e1 ++ (o:p) ++ e2
+
 append e1 e2 = "Value.append" ++ parens (e1 ++ "," ++ e2)
diff --git a/src/Compiler.hs b/src/Compiler.hs
--- a/src/Compiler.hs
+++ b/src/Compiler.hs
@@ -1,45 +1,49 @@
-
-module Main where
-
-import System.Environment
-import CompileToJS
-import Data.List (isPrefixOf)
-import GenerateHtml
-import Text.Blaze.Html.Renderer.String (renderHtml)
-
-main = getArgs >>= parse
-
-parse ("--help":_) = putStrLn usage
-parse ("--version":_) = putStrLn "The Elm Compiler 0.1.1.7"
-parse [loc,file]
-  | "--runtime-location=" `isPrefixOf` loc =
-      produceHtml (tail $ dropWhile (/='=') loc) file
-  | otherwise = putStrLn usageMini
-parse [file] = produceHtml "elm-mini.js" file
-parse _ = putStrLn usageMini
-
-produceHtml libLoc file = do
-  code <- readFile file
-  let name = takeWhile (/='.') file
-  case compile code of
-    Left err -> putStrLn err
-    Right jsCode -> writeFile (name ++ ".html") . renderHtml $
-                    generateHtml libLoc name jsCode
-
-usageMini =
-  "Usage: elm [OPTIONS] FILE\n\
-  \Try `elm --help' for more information."
-
-usage =
-  "Usage: elm [OPTIONS] FILE\n\
-  \Compile .elm files to .html files.\n\
-  \Example: elm --runtime-location=../elm-mini.js main.elm\n\
-  \\n\
-  \Resource Locations:\n\
-  \  --runtime-location   set the location of the Elm runtime (elm-mini.js)\n\
-  \\n\
-  \Compiler Information:\n\
-  \  --version            print the version information and exit\n\
-  \  --help               display this help and exit\n\
-  \\n\
+module Main where
+
+import Data.List (isPrefixOf)
+import CompileToJS
+import GenerateHtml
+import System.Environment
+import Text.Blaze.Html.Renderer.String (renderHtml)
+
+main :: IO ()
+main = getArgs >>= parse
+
+parse :: [String] -> IO ()
+parse ("--help":_) = putStrLn usage
+parse ("--version":_) = putStrLn "The Elm Compiler 0.1.2"
+parse [loc,file]
+  | "--runtime-location=" `isPrefixOf` loc =
+      produceHtml (tail $ dropWhile (/='=') loc) file
+  | otherwise = putStrLn usageMini
+parse [file] = produceHtml "elm-mini.js" file
+parse _ = putStrLn usageMini
+
+produceHtml :: String -> FilePath -> IO ()
+produceHtml libLoc file = do
+  code <- readFile file
+  let name = takeWhile (/='.') file
+  case compile code of
+    Left err -> putStrLn err
+    Right jsCode -> writeFile (name ++ ".html") . renderHtml $
+                    generateHtml libLoc name jsCode
+
+usageMini :: String
+usageMini =
+  "Usage: elm [OPTIONS] FILE\n\
+  \Try `elm --help' for more information."
+
+usage :: String
+usage =
+  "Usage: elm [OPTIONS] FILE\n\
+  \Compile .elm files to .html files.\n\
+  \Example: elm --runtime-location=../elm-mini.js main.elm\n\
+  \\n\
+  \Resource Locations:\n\
+  \  --runtime-location   set the location of the Elm runtime (elm-mini.js)\n\
+  \\n\
+  \Compiler Information:\n\
+  \  --version            print the version information and exit\n\
+  \  --help               display this help and exit\n\
+  \\n\
   \Elm home page: <http://elm-lang.org>"
diff --git a/src/ExtractNoscript.hs b/src/ExtractNoscript.hs
--- a/src/ExtractNoscript.hs
+++ b/src/ExtractNoscript.hs
@@ -1,26 +1,26 @@
-
-module ExtractNoscript (extract) where
-
-import Ast
-
-extract = concatMap (\s -> "<p>" ++ s ++ "</p>") . extract'
-
-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 e1 e2 -> f e1 ++ f e2
-      If eb et ef -> f et ++ f ef
-      Let defs e -> concatMap (f . snd) defs ++ f e
-      Var _ -> []
-      Case e cases -> concatMap (f . snd) cases
-      Data _ es -> concatMap f es
+
+module ExtractNoscript (extract) where
+
+import Ast
+
+extract = concatMap (\s -> "<p>" ++ s ++ "</p>") . extract'
+
+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 e1 e2 -> f e1 ++ f e2
+      If eb et ef -> f et ++ f ef
+      Let defs e -> concatMap (f . snd) defs ++ f e
+      Var _ -> []
+      Case e cases -> concatMap (f . snd) cases
+      Data _ es -> concatMap f es
       _ -> []
diff --git a/src/GenerateHtml.hs b/src/GenerateHtml.hs
--- a/src/GenerateHtml.hs
+++ b/src/GenerateHtml.hs
@@ -1,7 +1,8 @@
 {-# LANGUAGE OverloadedStrings #-}
-module GenerateHtml (generateHtml) where
+module GenerateHtml (generateHtml, body, css) where
 
 import Text.Blaze (preEscapedToMarkup)
+import Text.Blaze.Html (Html)
 import qualified Text.Blaze.Html5 as H
 import Text.Blaze.Html5 ((!))
 import qualified Text.Blaze.Html5.Attributes as A
@@ -10,7 +11,7 @@
 import CompileToJS
 import ExtractNoscript
 
-css = preEscapedToMarkup $
+css = H.style ! A.type_ "text/css" $ preEscapedToMarkup
       ("* { padding:0; margin:0; \
        \hyphens: auto; -moz-hyphens: auto;\
        \ -webkit-hyphens: auto; -ms-hyphens: auto; }\
@@ -23,6 +24,15 @@
 makeScript :: String -> H.Html
 makeScript s = H.script ! A.type_ "text/javascript" ! A.src (H.toValue s) $ ""
 
+-- |This function compiles Elm code into simple HTML.
+--
+--  Usage example:
+--
+-- > generateHtml "/elm-min.js" "Some title" [elmFile|elm-source/somePage.elm|]
+generateHtml :: String -- ^ Location of elm-min.js as expected by the browser
+             -> String -- ^ The page title
+             -> String -- ^ The elm source code.
+             -> Html
 generateHtml libLoc title source =
     let expr = initialize source
         js = compileToJS expr
@@ -34,9 +44,11 @@
         H.title . H.toHtml $ title
         makeScript libLoc
         H.script ! A.type_ "text/javascript" $ preEscapedToMarkup js
-        H.style ! A.type_ "text/css" $ css
-      H.body $ do
-        H.div ! A.id "widthChecker" ! A.style "width:100%; height:1px; position:absolute; top:-1px;" $ ""
-        H.span ! A.id "content" $ ""
-        H.script ! A.type_ "text/javascript" $ "Dispatcher.initialize()"
-        H.noscript $ preEscapedToMarkup noscript
+        css
+      H.body $ body noscript
+
+body noscript = do
+  H.div ! A.id "widthChecker" ! A.style "width:100%; height:1px; position:absolute; top:-1px;" $ ""
+  H.span ! A.id "content" $ ""
+  H.script ! A.type_ "text/javascript" $ "Dispatcher.initialize()"
+  H.noscript $ preEscapedToMarkup noscript 
diff --git a/src/Language/Elm.hs b/src/Language/Elm.hs
--- a/src/Language/Elm.hs
+++ b/src/Language/Elm.hs
@@ -1,15 +1,74 @@
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
+{- | This module exports the functions necessary for compiling Elm code into the
+     respective HTML, JS and CSS code.
 
-module Language.Elm where
+     The type class @'ElmSource'@ requires an instance for all types that the Elm compiler
+     understands. The provided instances for String, Text and QuasiQuoted Elm source code 
+     should be sufficient.
 
+     The documentation for the Elm language is available at <http://elm-lang.org/Documentation.elm>,
+     and many interactive examples are available at <http://elm-lang.org/Examples.elm>
+
+     Example implementations using Yesod and Happstack are available at <https://github.com/tazjin/Elm/tree/master/Examples>
+-}
+module Language.Elm (
+    ElmSource (..)
+    ) where
+
+import CompileToJS
+import ExtractNoscript
 import GenerateHtml
+import Initialize
 import Text.Blaze.Html (Html)
+import Language.Elm.Quasi
 
--- | The 'compileToHtml' function takes three string arguments: the
--- location of the Elm runtime (elm-mini.js), the title to be used in
--- the resulting HTML page, and the Elm source code. For example,
--- 
--- > compileToHtml "/elm-mini.js" "Hello, World!" "main = plainText \"Hello, World!\""
+import qualified Data.Text as TS
+import qualified Data.Text.Lazy as TL
 
-compileToHtml :: String -> String -> String -> Html
-compileToHtml libLoc fileName source =
-    generateHtml libLoc fileName source
+class ElmSource a where
+  -- |This function compiles Elm code to three separate parts: HTML, CSS,
+  --  and JavaScript. The HTML is only the contents of the body, so the three
+  --  parts must be combined in a basic HTML skeleton.
+  toParts :: a -> (Html, Html, String)
+
+  -- |This function compiles Elm code into a full HTML page.
+  toHtml :: String -- ^ Location of elm-min.js as expected by the browser
+         -> String -- ^ The page title
+         -> a      -- ^ The elm source code
+         -> Html
+
+instance ElmSource String where
+  toParts = toPartsHelper
+  toHtml = generateHtml
+
+instance ElmSource Elm where
+  toParts = toPartsHelper . TL.unpack . renderElm
+  toHtml elmL title  = generateHtml elmL title  . TL.unpack . renderElm
+
+-- |Strict text
+instance ElmSource TS.Text where
+  toParts = toPartsHelper . TS.unpack
+  toHtml elmL title = generateHtml elmL title . TS.unpack
+
+-- |Lazy text
+instance ElmSource TL.Text where
+  toParts = toPartsHelper . TL.unpack
+  toHtml elmL title = generateHtml elmL title . TL.unpack
+
+-- | (urlRenderFn, urlRenderFn -> Elm)
+instance ElmSource (t, t -> Elm) where
+  toParts (f, s) = toPartsHelper $ TL.unpack $ renderElm $ s f  
+  toHtml elmL title (f, s) = generateHtml elmL title $ TL.unpack $ renderElm $ s f
+
+-- | to be used without URL interpolation
+instance ElmSource (t -> Elm) where
+  toParts s = toPartsHelper $ TL.unpack $ renderElm $ s undefined
+  toHtml l t s = generateHtml l t $ TL.unpack $ renderElm $ s undefined
+
+
+-- build helper to avoid boilerplate repetition
+toPartsHelper :: String -> (Html, Html, String)
+toPartsHelper source = (html, css, js)
+  where expr = initialize source
+        js = compileToJS expr
+        html = body $ either id extract expr
diff --git a/src/Language/Elm/Quasi.hs b/src/Language/Elm/Quasi.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Elm/Quasi.hs
@@ -0,0 +1,93 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE CPP #-}
+{-# OPTIONS_GHC -fno-warn-missing-fields #-}
+
+-- | This module contains Shakespearean (see "Text.Shakespeare") templates for Elm.
+--   It introduces type-safe compile-time variable and URL interpolation. A typeclass
+--   @'ToElm'@ is provided for interpolated variables.
+--
+--   Further reading on Shakespearean templates: <http://www.yesodweb.com/book/templates>
+--
+--   Further reading on Elm: <http://elm-lang.org> 
+module Language.Elm.Quasi
+    ( -- * Functions
+      -- ** Template-Reading Functions
+      -- |These QuasiQuoters return functions of the type @(t -> 'Elm')@
+      --  where @t@ is the URL rendering function if type-safe URLs are used.
+      --
+      --  A usage example for both type-safe (Yesod) and standard path segment (Happstack)
+      --  URLs is provided in the Examples folder in the Git repository.
+      elm
+    , elmFile
+    , elmFileReload
+
+      -- * Datatypes
+    , Elm (..)
+
+      -- * Typeclass for interpolated variables
+    , ToElm (..)
+
+      -- ** Rendering Functions
+    , renderElm
+
+    ) where
+
+import Language.Haskell.TH.Quote (QuasiQuoter (..))
+import Language.Haskell.TH.Syntax
+import Data.Text.Lazy.Builder (Builder, fromText, toLazyText, fromLazyText)
+import Data.Monoid
+import qualified Data.Text as TS
+import qualified Data.Text.Lazy as TL
+import Text.Shakespeare
+
+-- | Render Elm to lazy Text.
+renderElm :: Elm -> TL.Text
+renderElm (Elm b) = toLazyText b
+
+-- | Newtype wrapper of 'Builder'.
+newtype Elm = Elm { unElm :: Builder }
+    deriving Monoid
+
+-- | A typeclass for types that can be interpolated in Elm templates.
+class ToElm a where
+    toElm :: a -> Builder
+instance ToElm [Char]  where toElm = fromLazyText . TL.pack
+instance ToElm TS.Text where toElm = fromText
+instance ToElm TL.Text where toElm = fromLazyText
+
+elmSettings :: Q ShakespeareSettings
+elmSettings = do
+  toJExp <- [|toElm|]
+  wrapExp <- [|Elm|]
+  unWrapExp <- [|unElm|]
+  return $ defaultShakespeareSettings { toBuilder = toJExp
+  , wrap = wrapExp
+  , unwrap = unWrapExp
+  }
+
+-- |QuasiQuoter for embedding Elm code inside of Haskell code.
+--
+--  Usage:
+-- @[elm|main = plaintext "Some elm code"|]@
+elm :: QuasiQuoter
+elm = QuasiQuoter { quoteExp = \s -> do
+    rs <- elmSettings
+    quoteExp (shakespeare rs) s
+    }
+
+-- |A Template Haskell function for embedding Elm code from external
+--  .elm files.
+--
+--  Usage:
+-- @$(elmFile "elm_source/index.elm")@
+elmFile :: FilePath -> Q Exp
+elmFile fp = do
+    rs <- elmSettings
+    shakespeareFile rs fp
+
+elmFileReload :: FilePath -> Q Exp
+elmFileReload fp = do
+    rs <- elmSettings
+    shakespeareFileReload rs fp
diff --git a/src/Parse/Binop.hs b/src/Parse/Binop.hs
--- a/src/Parse/Binop.hs
+++ b/src/Parse/Binop.hs
@@ -1,64 +1,64 @@
-module Binop (binops) where
-
-import Ast
-import Combinators
-import Control.Monad (liftM,guard)
-import Control.Monad.Error
-import Data.List (foldl',splitAt,elemIndices,group,groupBy,sortBy,find)
-import qualified Data.Map as Map
-import Data.Maybe (mapMaybe)
-
-data Assoc = L | Non | R deriving (Eq,Show)
-
-table = [ (9, R, ".")
-        , (7, L, "*"), (7, L, "/"), (7, L, "mod")
-        , (6, L, "+"), (6, L, "-")
-        , (5, R, ":" ), (5, R, "++")
-        , (4, Non, "<="), (4, Non, ">="), (4, Non, "<")
-        , (4, Non, "=="), (4, Non, "/="), (4, Non, ">")
-        , (3, R, "&&")
-        , (2, R, "||")
-        , (0, R, "$")
-        ]
-
-sortOps = sortBy (\(i,_,_) (j,_,_) -> compare i j)
-
-binops term anyOp = do
-  e <- term
-  (ops,es) <- liftM unzip $ star (do { op <- anyOp; e <- term; return (op,e) })
-  case binopOf Map.empty (sortOps table) ops (e:es) of
-    Right e -> return e
-    Left msg -> zero
-
-binopSplit seen opTable i ops es =
-    case (splitAt i ops, splitAt (i+1) es) of
-      ((befores, op:afters), (pres, posts)) ->
-          do e1 <- binopOf seen opTable befores pres
-             e2 <- binopOf seen opTable afters posts
-             return $ Binop op e1 e2
-
-binopOf _ _ _ [e] = return e
-binopOf _ [] ops es =
-    return $ foldl' (flip ($)) (head es) $ zipWith Binop ops (tail es)
-
-binopOf seen (tbl@((lvl, L, op):rest)) ops es =
-    case elemIndices op ops of
-      [] -> binopOf seen rest ops es
-      is -> case Map.lookup lvl seen of
-              Nothing -> binopSplit (Map.insert lvl (L,op) seen) tbl (last is) ops es
-              Just (L,_) -> binopSplit seen tbl (last is) ops es
-              Just (assoc,op') -> Left $ errorMessage lvl op L op' assoc
-binopOf seen (tbl@((lvl, assoc, op):rest)) ops es =
-    case elemIndices op ops of
-      [] -> binopOf seen rest ops es
-      i:_ -> case Map.lookup lvl seen of
-               Nothing -> binopSplit (Map.insert lvl (R,op) seen) tbl i ops es
-               Just (assoc',op') ->
-                   if assoc == assoc' && assoc /= Non then
-                       binopSplit seen tbl i ops es
-                   else Left $ errorMessage lvl op assoc op' assoc'
-
-errorMessage lvl op1 assoc1 op2 assoc2 =
-    "Cannot have (" ++ op1 ++ ") with [" ++ show assoc1 ++ " " ++
-    show lvl ++ "] and (" ++ op2 ++ ") with [" ++ show assoc2 ++ " " ++
-    show lvl ++ "]"
+module Binop (binops) where
+
+import Ast
+import Combinators
+import Control.Monad (liftM,guard)
+import Control.Monad.Error
+import Data.List (foldl',splitAt,elemIndices,group,groupBy,sortBy,find)
+import qualified Data.Map as Map
+import Data.Maybe (mapMaybe)
+
+data Assoc = L | Non | R deriving (Eq,Show)
+
+table = [ (9, R, ".")
+        , (7, L, "*"), (7, L, "/"), (7, L, "mod")
+        , (6, L, "+"), (6, L, "-")
+        , (5, R, ":" ), (5, R, "++")
+        , (4, Non, "<="), (4, Non, ">="), (4, Non, "<")
+        , (4, Non, "=="), (4, Non, "/="), (4, Non, ">")
+        , (3, R, "&&")
+        , (2, R, "||")
+        , (0, R, "$")
+        ]
+
+sortOps = sortBy (\(i,_,_) (j,_,_) -> compare i j)
+
+binops term anyOp = do
+  e <- term
+  (ops,es) <- liftM unzip $ star (do { op <- anyOp; e <- term; return (op,e) })
+  case binopOf Map.empty (sortOps table) ops (e:es) of
+    Right e -> return e
+    Left msg -> zero
+
+binopSplit seen opTable i ops es =
+    case (splitAt i ops, splitAt (i+1) es) of
+      ((befores, op:afters), (pres, posts)) ->
+          do e1 <- binopOf seen opTable befores pres
+             e2 <- binopOf seen opTable afters posts
+             return $ Binop op e1 e2
+
+binopOf _ _ _ [e] = return e
+binopOf _ [] ops es =
+    return $ foldl' (flip ($)) (head es) $ zipWith Binop ops (tail es)
+
+binopOf seen (tbl@((lvl, L, op):rest)) ops es =
+    case elemIndices op ops of
+      [] -> binopOf seen rest ops es
+      is -> case Map.lookup lvl seen of
+              Nothing -> binopSplit (Map.insert lvl (L,op) seen) tbl (last is) ops es
+              Just (L,_) -> binopSplit seen tbl (last is) ops es
+              Just (assoc,op') -> Left $ errorMessage lvl op L op' assoc
+binopOf seen (tbl@((lvl, assoc, op):rest)) ops es =
+    case elemIndices op ops of
+      [] -> binopOf seen rest ops es
+      i:_ -> case Map.lookup lvl seen of
+               Nothing -> binopSplit (Map.insert lvl (R,op) seen) tbl i ops es
+               Just (assoc',op') ->
+                   if assoc == assoc' && assoc /= Non then
+                       binopSplit seen tbl i ops es
+                   else Left $ errorMessage lvl op assoc op' assoc'
+
+errorMessage lvl op1 assoc1 op2 assoc2 =
+    "Cannot have (" ++ op1 ++ ") with [" ++ show assoc1 ++ " " ++
+    show lvl ++ "] and (" ++ op2 ++ ") with [" ++ show assoc2 ++ " " ++
+    show lvl ++ "]"
diff --git a/src/Parse/Combinators.hs b/src/Parse/Combinators.hs
--- a/src/Parse/Combinators.hs
+++ b/src/Parse/Combinators.hs
@@ -1,82 +1,82 @@
-module Combinators where
-import Control.Monad
-import Data.Char
-import Data.List (sortBy,foldl',foldl1')
-
-newtype Parser from to = Parser ([from] -> [(to,[from])])
---newtype Parser a = Parser (String -> [(a,String)])
-
-parse (Parser p) = p
-
-instance Monad (Parser from) where
-    return a = Parser (\cs -> [(a,cs)])
-    p >>= f  = Parser (\cs -> concat [parse (f a) cs' | (a,cs') <- parse p cs])
-
-instance MonadPlus (Parser from) where
-   mzero = Parser $ const []
-   mplus p q = Parser (\cs -> parse p cs ++ parse q cs)
-
--- True recursive descent, tries everything.
-p +++ q = mplus p q
-
--- Get the first parse.
-p +|+ q = Parser (\cs -> case parse (mplus p q) cs of
-                           [] -> []
-                           (x:xs) -> [x])
-
-zero = Parser $ const []
-
-item  = Parser (\cs -> case cs of
-                         [] -> []
-                         (c:cs) -> [(c,cs)])
-
-sat p = do {c <- item; if p c then return c else mzero}
-
-char c = sat (c ==)
-
-string ""     = return ""
-string (c:cs) = do {char c; string cs; return (c:cs)}
-
-star p = plus p +++ return []
-plus p = do {a <- p; as <- star p; return (a:as)}
-
-optional p = (Just `liftM` p) +++ return Nothing
-
-nospace = guard . (==0) . length =<< space
-space = star $ sat isSpace
-space1 = plus $ sat isSpace
-newline = do
-  star $ char ' ' +++ char '\t'
-  char '\n'
-  space
-  return ""
-
-digit = do {x <- sat isDigit; return (ord x - ord '0')}
-integer = do {i <- plus digit; return $ foldl' (\a d -> 10 * a + d) 0 i}
-
-variable = do
-  shd <- sat isLower;
-  stl <- star $ sat (\c -> isAlphaNum c || c == '_')
-  return $ shd:stl
-
-sepBy sep p = sepBy1 sep p +++ return []
-
-sepBy1 sep p = do
-  x <- p
-  xs <- star (sep >> p)
-  return $ x:xs
-
-select = foldl1' (+|+)
-
-chainl p op a = chainl1 p op +++ return a
-chainl1 p op = do {a <- p; rest a}
-                where
-                  rest a = (do f <- op
-                               b <- p
-                               rest (f a b)) +++ return a
-
-extractResult err parse =
-    case parse of
-      (r,[]) : _ -> Right r
-      _ : rest -> extractResult err rest
-      [] -> Left err
+module Combinators where
+import Control.Monad
+import Data.Char
+import Data.List (sortBy,foldl',foldl1')
+
+newtype Parser from to = Parser ([from] -> [(to,[from])])
+--newtype Parser a = Parser (String -> [(a,String)])
+
+parse (Parser p) = p
+
+instance Monad (Parser from) where
+    return a = Parser (\cs -> [(a,cs)])
+    p >>= f  = Parser (\cs -> concat [parse (f a) cs' | (a,cs') <- parse p cs])
+
+instance MonadPlus (Parser from) where
+   mzero = Parser $ const []
+   mplus p q = Parser (\cs -> parse p cs ++ parse q cs)
+
+-- True recursive descent, tries everything.
+p +++ q = mplus p q
+
+-- Get the first parse.
+p +|+ q = Parser (\cs -> case parse (mplus p q) cs of
+                           [] -> []
+                           (x:xs) -> [x])
+
+zero = Parser $ const []
+
+item  = Parser (\cs -> case cs of
+                         [] -> []
+                         (c:cs) -> [(c,cs)])
+
+sat p = do {c <- item; if p c then return c else mzero}
+
+char c = sat (c ==)
+
+string ""     = return ""
+string (c:cs) = do {char c; string cs; return (c:cs)}
+
+star p = plus p +++ return []
+plus p = do {a <- p; as <- star p; return (a:as)}
+
+optional p = (Just `liftM` p) +++ return Nothing
+
+nospace = guard . (==0) . length =<< space
+space = star $ sat isSpace
+space1 = plus $ sat isSpace
+newline = do
+  star $ char ' ' +++ char '\t'
+  char '\n'
+  space
+  return ""
+
+digit = do {x <- sat isDigit; return (ord x - ord '0')}
+integer = do {i <- plus digit; return $ foldl' (\a d -> 10 * a + d) 0 i}
+
+variable = do
+  shd <- sat isLower;
+  stl <- star $ sat (\c -> isAlphaNum c || c == '_')
+  return $ shd:stl
+
+sepBy sep p = sepBy1 sep p +++ return []
+
+sepBy1 sep p = do
+  x <- p
+  xs <- star (sep >> p)
+  return $ x:xs
+
+select = foldl1' (+|+)
+
+chainl p op a = chainl1 p op +++ return a
+chainl1 p op = do {a <- p; rest a}
+                where
+                  rest a = (do f <- op
+                               b <- p
+                               rest (f a b)) +++ return a
+
+extractResult err parse =
+    case parse of
+      (r,[]) : _ -> Right r
+      _ : rest -> extractResult err rest
+      [] -> Left err
diff --git a/src/Parse/Lexer.hs b/src/Parse/Lexer.hs
--- a/src/Parse/Lexer.hs
+++ b/src/Parse/Lexer.hs
@@ -1,84 +1,84 @@
-
-module Lexer (tokenize) where
-
-import Control.Applicative ((<|>), (<$>), (<*>))
-import Data.Char (isSymbol)
-import Text.Parsec (Parsec, alphaNum, anyChar, char, choice, digit, eof, letter,
-                    many, many1, manyTill, newline, notFollowedBy, oneOf, parse,
-                    satisfy, string, try, upper)
-import Tokens
-import Control.Monad (liftM)
-
-token :: Parsec String u Token
-token = NUMBER <$> integer
-    <|> whitespace
-    <|> chrs [ ('(',LPAREN)  , (')',RPAREN)
-             , ('{',LBRACE)  , ('}',RBRACE)
-             , ('[',LBRACKET), (']',RBRACKET)
-             , (',',COMMA)   , (';',SEMI), ('_',UNDERSCORE)
-             , ('\\',LAMBDA) , ('\x03BB',LAMBDA) ]
-    <|> reserveds [ ("True",TRUE), ("False",FALSE)
-                  , ("if",IF), ("then",THEN), ("else",ELSE)
-                  , ("case",CASE), ("of",OF), ("data", DATA) 
-                  , ("let",LET), ("in",IN) ]
-    <|> do { char '`'; v <- variable; char '`'; return $ OP v }
-    <|> anyOp
-    <|> do { char '"'; s <- many $ backslashed <|> satisfy (/='"'); char '"'
-           ; return $ STRING s}
-    <|> do { char '\''; c <- backslashed <|> satisfy (/='\''); char '\''
-           ; return $ CHAR c}
-    <|> (ID <$> variable)
-    <|> typeVar
-    <|> do { try $ string "\r\n" <|> string "\n"; return NEWLINE }
-
-chrs :: [(Char, Token)] -> Parsec String u Token
-chrs = choice . map chr
-    where chr (c, t) = char c >> return t
-
-reserveds :: [(String, Token)] -> Parsec String u Token
-reserveds = choice . map reserved
-    where reserved (s, t) = try $ string s >>
-                                  notFollowedBy (alphaNum <|> char '_') >>
-                                  return t
-
-anyOp = do op <- many1 (satisfy isSymbol <|> oneOf "+-/*=.$<>:&|^?%#@~!")
-           case op of { ".." -> return DOT2
-                      ; "->" -> return ARROW; "\8594" -> return ARROW
-                      ; _ -> return $ OP op }
-
-backslashed :: Parsec String u Char
-backslashed = do { char '\\'; c <- anyChar
-                 ; return . read $ ['\'','\\',c,'\''] }
-
-integer :: Parsec String u Int
-integer = read <$> many1 digit
-
-variable :: Parsec String u String
-variable = identifier $ letter <|> char '_'
-
-typeVar :: Parsec String u Token
-typeVar = TYPE <$> identifier upper
-
-identifier :: Parsec String u Char -> Parsec String u String
-identifier c = (:) <$> c <*> (many $ alphaNum <|> oneOf "_\'")
-
-----  White Space and comments  ----
-
-whitespace = (lineComment >> return NEWLINE) <|>
-             (many1 (multiComment <|> many1 (char ' ')) >> return SPACES)
-lineComment = do try $ string "--"
-                 manyTill anyChar $ newline <|> (eof >> return '\n')
-
-multiComment = do { try $ string "{-"; closeComment }
-closeComment = manyTill anyChar . choice $
-               [ try $ string "-}"
-               , do { try $ string "{-"; closeComment; closeComment }
-               ]
-
-tokenParser :: Parsec String u [Token]
-tokenParser = many1 token
-
-tokenize :: String -> Either String [Token]
-tokenize s = case parse tokenParser "" s of
-               Right ts -> Right ts
-               Left err -> Left $ "Syntax error: " ++ show err
+
+module Lexer (tokenize) where
+
+import Control.Applicative ((<|>), (<$>), (<*>))
+import Data.Char (isSymbol)
+import Text.Parsec (Parsec, alphaNum, anyChar, char, choice, digit, eof, letter,
+                    many, many1, manyTill, newline, notFollowedBy, oneOf, parse,
+                    satisfy, string, try, upper)
+import Tokens
+import Control.Monad (liftM)
+
+token :: Parsec String u Token
+token = NUMBER <$> integer
+    <|> whitespace
+    <|> chrs [ ('(',LPAREN)  , (')',RPAREN)
+             , ('{',LBRACE)  , ('}',RBRACE)
+             , ('[',LBRACKET), (']',RBRACKET)
+             , (',',COMMA)   , (';',SEMI), ('_',UNDERSCORE)
+             , ('\\',LAMBDA) , ('\x03BB',LAMBDA) ]
+    <|> reserveds [ ("True",TRUE), ("False",FALSE)
+                  , ("if",IF), ("then",THEN), ("else",ELSE)
+                  , ("case",CASE), ("of",OF), ("data", DATA) 
+                  , ("let",LET), ("in",IN) ]
+    <|> do { char '`'; v <- variable; char '`'; return $ OP v }
+    <|> anyOp
+    <|> do { char '"'; s <- many $ backslashed <|> satisfy (/='"'); char '"'
+           ; return $ STRING s}
+    <|> do { char '\''; c <- backslashed <|> satisfy (/='\''); char '\''
+           ; return $ CHAR c}
+    <|> (ID <$> variable)
+    <|> typeVar
+    <|> do { try $ string "\r\n" <|> string "\n"; return NEWLINE }
+
+chrs :: [(Char, Token)] -> Parsec String u Token
+chrs = choice . map chr
+    where chr (c, t) = char c >> return t
+
+reserveds :: [(String, Token)] -> Parsec String u Token
+reserveds = choice . map reserved
+    where reserved (s, t) = try $ string s >>
+                                  notFollowedBy (alphaNum <|> char '_') >>
+                                  return t
+
+anyOp = do op <- many1 (satisfy isSymbol <|> oneOf "+-/*=.$<>:&|^?%#@~!")
+           case op of { ".." -> return DOT2
+                      ; "->" -> return ARROW; "\8594" -> return ARROW
+                      ; _ -> return $ OP op }
+
+backslashed :: Parsec String u Char
+backslashed = do { char '\\'; c <- anyChar
+                 ; return . read $ ['\'','\\',c,'\''] }
+
+integer :: Parsec String u Int
+integer = read <$> many1 digit
+
+variable :: Parsec String u String
+variable = identifier $ letter <|> char '_'
+
+typeVar :: Parsec String u Token
+typeVar = TYPE <$> identifier upper
+
+identifier :: Parsec String u Char -> Parsec String u String
+identifier c = (:) <$> c <*> (many $ alphaNum <|> oneOf "_\'")
+
+----  White Space and comments  ----
+
+whitespace = (lineComment >> return NEWLINE) <|>
+             (many1 (multiComment <|> many1 (char ' ')) >> return SPACES)
+lineComment = do try $ string "--"
+                 manyTill anyChar $ newline <|> (eof >> return '\n')
+
+multiComment = do { try $ string "{-"; closeComment }
+closeComment = manyTill anyChar . choice $
+               [ try $ string "-}"
+               , do { try $ string "{-"; closeComment; closeComment }
+               ]
+
+tokenParser :: Parsec String u [Token]
+tokenParser = many1 token
+
+tokenize :: String -> Either String [Token]
+tokenize s = case parse tokenParser "" s of
+               Right ts -> Right ts
+               Left err -> Left $ "Syntax error: " ++ show err
diff --git a/src/Parse/ParsePatterns.hs b/src/Parse/ParsePatterns.hs
--- a/src/Parse/ParsePatterns.hs
+++ b/src/Parse/ParsePatterns.hs
@@ -1,31 +1,31 @@
-module ParsePatterns (patternTerm, patternExpr) where
-
-import Ast
-import Combinators
-import Data.Char (isUpper)
-import ParserLib
-import Tokens
-import Control.Monad (liftM)
-
-patternBasic =
-    (t UNDERSCORE >> return PAnything) +|+
-    (do { x@(c:_) <- var ;
-          if isUpper c then PData x `liftM` star patternTerm
-                       else return $ PVar x })
-
-patternTuple = do
-  t LPAREN; ps <- sepBy1 (t COMMA) patternExpr; t RPAREN
-  return $ case ps of { [p] -> p; _ -> ptuple ps }
-
-patternCons = do
-  p <- patternTerm
-  colon <- optional $ opParser (==":")
-  case colon of
-    Just ":" -> pcons p `liftM` patternExpr
-    Nothing -> return p
-
-patternList = do
-  t LBRACKET; ps <- sepBy (t COMMA) patternExpr; t RBRACKET; return (plist ps)
-
-patternTerm = patternTuple +|+ patternList +|+ patternBasic
-patternExpr = patternTuple +|+ patternList +|+ patternCons
+module ParsePatterns (patternTerm, patternExpr) where
+
+import Ast
+import Combinators
+import Data.Char (isUpper)
+import ParserLib
+import Tokens
+import Control.Monad (liftM)
+
+patternBasic =
+    (t UNDERSCORE >> return PAnything) +|+
+    (do { x@(c:_) <- var ;
+          if isUpper c then PData x `liftM` star patternTerm
+                       else return $ PVar x })
+
+patternTuple = do
+  t LPAREN; ps <- sepBy1 (t COMMA) patternExpr; t RPAREN
+  return $ case ps of { [p] -> p; _ -> ptuple ps }
+
+patternCons = do
+  p <- patternTerm
+  colon <- optional $ opParser (==":")
+  case colon of
+    Just ":" -> pcons p `liftM` patternExpr
+    Nothing -> return p
+
+patternList = do
+  t LBRACKET; ps <- sepBy (t COMMA) patternExpr; t RBRACKET; return (plist ps)
+
+patternTerm = patternTuple +|+ patternList +|+ patternBasic
+patternExpr = patternTuple +|+ patternList +|+ patternCons
diff --git a/src/Parse/ParseTypes.hs b/src/Parse/ParseTypes.hs
--- a/src/Parse/ParseTypes.hs
+++ b/src/Parse/ParseTypes.hs
@@ -1,69 +1,69 @@
-module ParseTypes where
-
-import Ast
-import Combinators
-import Data.Char (isUpper,isLower)
-import Data.Maybe (fromMaybe)
-import Data.List (lookup)
-import ParserLib
-import Tokens
-import Types
-import Guid
-import Control.Monad (liftM)
-
-data ParseType = VarPT String
-               | LambdaPT ParseType ParseType
-               | ADTPT String [ParseType]
-
-listPT t = ADTPT "List" [t]
-tuplePT ts = ADTPT ("Tuple" ++ show (length ts)) ts
-
-typeVar = liftM VarPT lowVar
-typeList  = do t LBRACKET; te <- typeExpr; t RBRACKET; return $ listPT te
-typeTuple = do { t LPAREN; ts <- sepBy (t COMMA) typeExpr; t RPAREN
-               ; return $ case ts of { [t] -> t ; _ -> tuplePT ts } }
-typeUnambiguous = typeList +|+ typeTuple
-
-typeSimple = liftM VarPT var
-typeApp = do name <- capVar
-             args <- star (typeSimple +|+ typeUnambiguous)
-             return $ case args of
-                        [] -> VarPT name
-                        _  -> ADTPT name args
-                     
-typeExpr = do
-  t1 <- typeVar +|+ typeApp +|+ typeUnambiguous
-  arrow <- optional $ t ARROW
-  case arrow of Just ARROW -> LambdaPT t1 `liftM` typeExpr
-                Nothing -> return t1
-
-typeConstructor = do name <- capVar
-                     args <- star (typeSimple +|+ typeUnambiguous)
-                     return $ (,) name args
-
-datatype = do
-  t DATA ; name <- capVar ; args <- star lowVar ; assign
-  tcs <- sepBy1 (opParser (=="|")) typeConstructor
-  return $ (map fst tcs , map toFunc tcs , toTypes name args tcs)
-
-beta = VarT `liftM` guid
-
-toFunc (name,args) = foldr Lambda (Data name $ map Var argNames) argNames
-    where argNames = map (("a"++) . show) [1..length args]
-
-toTypes name args constructors = do
-  pairs <- mapM (\x -> (,) x `liftM` guid) args
-  return $ map (toType pairs . ADT name $ map (VarT . snd) pairs) constructors
-
-toType pairs outType (name,args) =
-    foldr (==>) outType (map toT args)
-    where toT (LambdaPT t1 t2)  = toT t1 ==> toT t2
-          toT (ADTPT name args) = ADT name $ map toT args
-          toT (VarPT x@(c:_))
-              | isLower c = VarT . fromMaybe (-1) $ lookup x pairs
-              | otherwise = case x of "Int" -> IntT
-                                      "Number" -> IntT
-                                      "String" -> StringT
-                                      "Char" -> CharT
-                                      "Bool" -> BoolT
-                                      _ -> ADT x []
+module ParseTypes where
+
+import Ast
+import Combinators
+import Data.Char (isUpper,isLower)
+import Data.Maybe (fromMaybe)
+import Data.List (lookup)
+import ParserLib
+import Tokens
+import Types
+import Guid
+import Control.Monad (liftM)
+
+data ParseType = VarPT String
+               | LambdaPT ParseType ParseType
+               | ADTPT String [ParseType]
+
+listPT t = ADTPT "List" [t]
+tuplePT ts = ADTPT ("Tuple" ++ show (length ts)) ts
+
+typeVar = liftM VarPT lowVar
+typeList  = do t LBRACKET; te <- typeExpr; t RBRACKET; return $ listPT te
+typeTuple = do { t LPAREN; ts <- sepBy (t COMMA) typeExpr; t RPAREN
+               ; return $ case ts of { [t] -> t ; _ -> tuplePT ts } }
+typeUnambiguous = typeList +|+ typeTuple
+
+typeSimple = liftM VarPT var
+typeApp = do name <- capVar
+             args <- star (typeSimple +|+ typeUnambiguous)
+             return $ case args of
+                        [] -> VarPT name
+                        _  -> ADTPT name args
+                     
+typeExpr = do
+  t1 <- typeVar +|+ typeApp +|+ typeUnambiguous
+  arrow <- optional $ t ARROW
+  case arrow of Just ARROW -> LambdaPT t1 `liftM` typeExpr
+                Nothing -> return t1
+
+typeConstructor = do name <- capVar
+                     args <- star (typeSimple +|+ typeUnambiguous)
+                     return $ (,) name args
+
+datatype = do
+  t DATA ; name <- capVar ; args <- star lowVar ; assign
+  tcs <- sepBy1 (opParser (=="|")) typeConstructor
+  return $ (map fst tcs , map toFunc tcs , toTypes name args tcs)
+
+beta = VarT `liftM` guid
+
+toFunc (name,args) = foldr Lambda (Data name $ map Var argNames) argNames
+    where argNames = map (("a"++) . show) [1..length args]
+
+toTypes name args constructors = do
+  pairs <- mapM (\x -> (,) x `liftM` guid) args
+  return $ map (toType pairs . ADT name $ map (VarT . snd) pairs) constructors
+
+toType pairs outType (name,args) =
+    foldr (==>) outType (map toT args)
+    where toT (LambdaPT t1 t2)  = toT t1 ==> toT t2
+          toT (ADTPT name args) = ADT name $ map toT args
+          toT (VarPT x@(c:_))
+              | isLower c = VarT . fromMaybe (-1) $ lookup x pairs
+              | otherwise = case x of "Int" -> IntT
+                                      "Number" -> IntT
+                                      "String" -> StringT
+                                      "Char" -> CharT
+                                      "Bool" -> BoolT
+                                      _ -> ADT x []
diff --git a/src/Parse/Parser.hs b/src/Parse/Parser.hs
--- a/src/Parse/Parser.hs
+++ b/src/Parse/Parser.hs
@@ -1,121 +1,121 @@
-module Parser where
-
-import Ast
-import Binop (binops)
-import Combinators
-import Control.Monad (liftM)
-import Data.List (foldl')
-import Guid
-import Lexer
-import ParserLib
-import ParseTypes (datatype)
-import ParsePatterns
-import Tokens
-import Types (Type (VarT))
-
---------  Basic Terms  --------
-
-numTerm = do { whitespace; t <- item
-             ; case t of { NUMBER n -> return $ Number n; _ -> zero } }
-strTerm = do { whitespace; t <- item
-             ; case t of { STRING cs -> return $ Str cs
-                         ; _ -> zero } }
-
-varTerm = Var `liftM` var
-chrTerm = Chr `liftM` chr
-
-trueTerm = do { t TRUE; return $ Boolean True }
-falseTerm = do { t FALSE; return $ Boolean False }
-
-
---------  Complex Terms  --------
-
-listTerm = (do { t LBRACKET; start <- expr; t DOT2; end <- expr; t RBRACKET
-                ; return $ Range start end }) +|+
-            (do { t LBRACKET; es <- sepBy (t COMMA) expr; t RBRACKET
-                ; return $ list es })
-
-parensTerm = (do { t LPAREN; op <- anyOp; t RPAREN
-                  ; return . Lambda "x" . Lambda "y" $
-                           Binop op (Var "x") (Var "y") }) +|+
-              (do { t LPAREN; es <- sepBy (t COMMA) expr; t RPAREN
-                  ; return $ case es of { [e] -> e; _ -> tuple es } })
-
-term = select [ numTerm
-              , strTerm
-              , accessible varTerm
-              , chrTerm
-              , trueTerm
-              , falseTerm
-              , listTerm 
-              , accessible parensTerm
-              ]
-
---------  Applications  --------
-
-appExpr = do
-  tlist <- plus term
-  return $ case tlist of
-             t:[] -> t
-             t:ts -> foldl' App t ts
-
-
---------  Expressions with infix operators  --------
-
-binaryExpr = binops appExpr anyOp
-
-
---------  Normal Expressions  --------
-
-ifExpr = do { t IF; e1 <- expr; t THEN; e2 <- expr; t ELSE; e3 <- expr
-             ; return $ If e1 e2 e3 }
-
-lambdaExpr = do { t LAMBDA; vs <- plus var; t ARROW; e <- expr
-                 ; return $ foldr Lambda e vs }
-
-assignExpr = whitespace >> assignExprNospace
-assignExprNospace = do
-  p:ps <- plus patternTerm; assign; e <- expr
-  case p:ps of
-    PVar x : _ -> return (x, foldr func e ps)
-        where func PAnything e' = Lambda "_" e'
-              func (PVar x)  e' = Lambda x e'
-              func p' e' = Lambda "_temp" (Case (Var "_temp") [(p', e')])
---    _ : [] -> return $ \hole -> Case e [(p,hole)]
-    _ -> zero
-
-letExpr = do
-  t LET; brace <- optional $ t LBRACE
-  case brace of
-    Nothing -> do f <- assignExpr; t IN; e <- expr; return (Let [f] e)
-    Just LBRACE -> do fs <- sepBy1 (t SEMI) assignExpr; t RBRACE; t IN;
-                      e <- expr; return (Let fs e)
-
-caseExpr = do
-  t CASE; e <- expr; t OF; t LBRACE
-  cases <- sepBy1 (t SEMI)
-           (do { p <- patternExpr; t ARROW; e <- expr; return (p,e) })
-  t RBRACE
-  return $ Case e cases
-
---------  All Expressions  --------
-
-expr = select [ letExpr
-              , binaryExpr
-              , ifExpr
-              , caseExpr
-              , lambdaExpr
-              ]
-
-def = do (f,e) <- assignExprNospace
-         return ([f], [e], guid >>= \x -> return [VarT x])
-
-defs = do
-  (fss,ess,tss) <- unzip3 `liftM` plus (whitespace >> plus (sat (==NEWLINE)) >> def +|+ datatype)
-  let (fs,es,ts) = (concat fss, concat ess, concat `liftM` sequence tss)
-  star $ sat (==NEWLINE) +|+ sat (==SPACES)
-  return (Let (zip fs es) (Var "main"), liftM (zip fs) ts)
-
-err = "Parse Error: Better error messages to come!"
-toExpr = extractResult err . parse expr
-toDefs = extractResult err . parse defs . (NEWLINE:)
+module Parser where
+
+import Ast
+import Binop (binops)
+import Combinators
+import Control.Monad (liftM)
+import Data.List (foldl')
+import Guid
+import Lexer
+import ParserLib
+import ParseTypes (datatype)
+import ParsePatterns
+import Tokens
+import Types (Type (VarT))
+
+--------  Basic Terms  --------
+
+numTerm = do { whitespace; t <- item
+             ; case t of { NUMBER n -> return $ Number n; _ -> zero } }
+strTerm = do { whitespace; t <- item
+             ; case t of { STRING cs -> return $ Str cs
+                         ; _ -> zero } }
+
+varTerm = Var `liftM` var
+chrTerm = Chr `liftM` chr
+
+trueTerm = do { t TRUE; return $ Boolean True }
+falseTerm = do { t FALSE; return $ Boolean False }
+
+
+--------  Complex Terms  --------
+
+listTerm = (do { t LBRACKET; start <- expr; t DOT2; end <- expr; t RBRACKET
+                ; return $ Range start end }) +|+
+            (do { t LBRACKET; es <- sepBy (t COMMA) expr; t RBRACKET
+                ; return $ list es })
+
+parensTerm = (do { t LPAREN; op <- anyOp; t RPAREN
+                  ; return . Lambda "x" . Lambda "y" $
+                           Binop op (Var "x") (Var "y") }) +|+
+              (do { t LPAREN; es <- sepBy (t COMMA) expr; t RPAREN
+                  ; return $ case es of { [e] -> e; _ -> tuple es } })
+
+term = select [ numTerm
+              , strTerm
+              , accessible varTerm
+              , chrTerm
+              , trueTerm
+              , falseTerm
+              , listTerm 
+              , accessible parensTerm
+              ]
+
+--------  Applications  --------
+
+appExpr = do
+  tlist <- plus term
+  return $ case tlist of
+             t:[] -> t
+             t:ts -> foldl' App t ts
+
+
+--------  Expressions with infix operators  --------
+
+binaryExpr = binops appExpr anyOp
+
+
+--------  Normal Expressions  --------
+
+ifExpr = do { t IF; e1 <- expr; t THEN; e2 <- expr; t ELSE; e3 <- expr
+             ; return $ If e1 e2 e3 }
+
+lambdaExpr = do { t LAMBDA; vs <- plus var; t ARROW; e <- expr
+                 ; return $ foldr Lambda e vs }
+
+assignExpr = whitespace >> assignExprNospace
+assignExprNospace = do
+  p:ps <- plus patternTerm; assign; e <- expr
+  case p:ps of
+    PVar x : _ -> return (x, foldr func e ps)
+        where func PAnything e' = Lambda "_" e'
+              func (PVar x)  e' = Lambda x e'
+              func p' e' = Lambda "_temp" (Case (Var "_temp") [(p', e')])
+--    _ : [] -> return $ \hole -> Case e [(p,hole)]
+    _ -> zero
+
+letExpr = do
+  t LET; brace <- optional $ t LBRACE
+  case brace of
+    Nothing -> do f <- assignExpr; t IN; e <- expr; return (Let [f] e)
+    Just LBRACE -> do fs <- sepBy1 (t SEMI) assignExpr; t RBRACE; t IN;
+                      e <- expr; return (Let fs e)
+
+caseExpr = do
+  t CASE; e <- expr; t OF; t LBRACE
+  cases <- sepBy1 (t SEMI)
+           (do { p <- patternExpr; t ARROW; e <- expr; return (p,e) })
+  t RBRACE
+  return $ Case e cases
+
+--------  All Expressions  --------
+
+expr = select [ letExpr
+              , binaryExpr
+              , ifExpr
+              , caseExpr
+              , lambdaExpr
+              ]
+
+def = do (f,e) <- assignExprNospace
+         return ([f], [e], guid >>= \x -> return [VarT x])
+
+defs = do
+  (fss,ess,tss) <- unzip3 `liftM` plus (whitespace >> plus (sat (==NEWLINE)) >> def +|+ datatype)
+  let (fs,es,ts) = (concat fss, concat ess, concat `liftM` sequence tss)
+  star $ sat (==NEWLINE) +|+ sat (==SPACES)
+  return (Let (zip fs es) (Var "main"), liftM (zip fs) ts)
+
+err = "Parse Error: Better error messages to come!"
+toExpr = extractResult err . parse expr
+toDefs = extractResult err . parse defs . (NEWLINE:)
diff --git a/src/Parse/ParserLib.hs b/src/Parse/ParserLib.hs
--- a/src/Parse/ParserLib.hs
+++ b/src/Parse/ParserLib.hs
@@ -1,38 +1,38 @@
-module ParserLib where
-
-import Ast
-import Combinators
-import Data.Char (isUpper,isLower)
-import Control.Monad (liftM,guard)
-import Tokens
-
-varNoSpace = do { t <- item; case t of { ID v -> return v; _ -> zero } }
-var = whitespace >> varNoSpace
-capVar = do whitespace; t <- item
-            case t of { ID (v:vs) -> guard (isUpper v) >> return (v:vs) ; _ -> zero }
-lowVar = do whitespace; t <- item
-            case t of { ID (v:vs) -> guard (isLower v) >> return (v:vs) ; _ -> zero }
-
-chr = do { whitespace; t <- item; case t of { CHAR c -> return c; _ -> zero } }
-
-tNoSpace token = sat (==token)
-tWithSpace token = forcedWS >> sat (==token)
-t token = whitespace >> sat (==token)
-
-forcedWS = do { sat (==SPACES); star nl_space } +|+ plus nl_space
-    where nl_space = plus (sat (==NEWLINE)) >> sat (==SPACES)
-whitespace = optional forcedWS
-
-accessible exp = do
-  e <- exp
-  access <- optional $ opParserNospace (==".")
-  case access of
-    Just "." -> accessible (Access e `liftM` var)
-    Nothing -> return e
-
-opParserNospace pred =
-    do { t <- item
-       ; case t of { OP op -> if pred op then return op else zero; _ -> zero } }
-opParser pred = whitespace >> opParserNospace pred
-anyOp  = opParser (const True)
-assign = opParser (=="=")
+module ParserLib where
+
+import Ast
+import Combinators
+import Data.Char (isUpper,isLower)
+import Control.Monad (liftM,guard)
+import Tokens
+
+varNoSpace = do { t <- item; case t of { ID v -> return v; _ -> zero } }
+var = whitespace >> varNoSpace
+capVar = do whitespace; t <- item
+            case t of { ID (v:vs) -> guard (isUpper v) >> return (v:vs) ; _ -> zero }
+lowVar = do whitespace; t <- item
+            case t of { ID (v:vs) -> guard (isLower v) >> return (v:vs) ; _ -> zero }
+
+chr = do { whitespace; t <- item; case t of { CHAR c -> return c; _ -> zero } }
+
+tNoSpace token = sat (==token)
+tWithSpace token = forcedWS >> sat (==token)
+t token = whitespace >> sat (==token)
+
+forcedWS = do { sat (==SPACES); star nl_space } +|+ plus nl_space
+    where nl_space = plus (sat (==NEWLINE)) >> sat (==SPACES)
+whitespace = optional forcedWS
+
+accessible exp = do
+  e <- exp
+  access <- optional $ opParserNospace (==".")
+  case access of
+    Just "." -> accessible (Access e `liftM` var)
+    Nothing -> return e
+
+opParserNospace pred =
+    do { t <- item
+       ; case t of { OP op -> if pred op then return op else zero; _ -> zero } }
+opParser pred = whitespace >> opParserNospace pred
+anyOp  = opParser (const True)
+assign = opParser (=="=")
diff --git a/src/Rename.hs b/src/Rename.hs
--- a/src/Rename.hs
+++ b/src/Rename.hs
@@ -1,88 +1,88 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-module Rename (rename) where
-
-import Ast
-import Control.Arrow (first)
-import Control.Monad (ap, liftM, foldM, mapM, Monad)
-import Control.Monad.State (evalState, State, get, put)
-import Data.Char (isLower)
-import Guid
-
-rename :: Expr -> Expr
-rename = run . rename' id
-
-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 -> do
-                let (vs,es) = unzip defs
-                env' <- foldM (\acc x -> snd `liftM` extend acc x) env vs
-                es' <- mapM (rename' env') es; re <- rename' env' e
-                return $ Let (zip (map env' vs) es') re
-
-      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
-
-extend :: (String -> String) -> String -> GuidCounter (String, String -> String)
-extend env x = do
-  n <- guid
-  let rx = x ++ "_" ++ show n
-  return (rx, \y -> if y == x then rx else env y)
-
-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)
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module Rename (rename) where
+
+import Ast
+import Control.Arrow (first)
+import Control.Monad (ap, liftM, foldM, mapM, Monad)
+import Control.Monad.State (evalState, State, get, put)
+import Data.Char (isLower)
+import Guid
+
+rename :: Expr -> Expr
+rename = run . rename' id
+
+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 -> do
+                let (vs,es) = unzip defs
+                env' <- foldM (\acc x -> snd `liftM` extend acc x) env vs
+                es' <- mapM (rename' env') es; re <- rename' env' e
+                return $ Let (zip (map env' vs) es') re
+
+      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
+
+extend :: (String -> String) -> String -> GuidCounter (String, String -> String)
+extend env x = do
+  n <- guid
+  let rx = x ++ "_" ++ show n
+  return (rx, \y -> if y == x then rx else env y)
+
+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)
diff --git a/src/Server.hs b/src/Server.hs
deleted file mode 100644
--- a/src/Server.hs
+++ /dev/null
@@ -1,58 +0,0 @@
-
-module Main where
-
-import Control.Monad (msum,guard)
-import Control.Monad.Trans (MonadIO(liftIO))
-import Data.List (isPrefixOf, isSuffixOf)
-import Happstack.Server
-import Happstack.Server.Compression
-import System.Environment
-import Language.Elm
-
-serve :: String -> IO ()
-serve libLoc = do
-  putStrLn "Elm Server 0.1.1.7: running at <http://localhost:8000>"
-  simpleHTTP nullConf $ do
-         compressedResponseFilter
-         msum [ uriRest (serveElm libLoc)
-              , serveDirectory EnableBrowsing [] "."
-              ]
-
-pageTitle fp =
-    reverse . takeWhile (/='/') . drop 1 . dropWhile (/='.') $ reverse fp
-
-serveElm libLoc fp = do
-  let ('/':path) = fp
-  guard (".elm" `isSuffixOf` path)
-  content <- liftIO (readFile path)
-  ok . toResponse $ compileToHtml libLoc (pageTitle path) content
-
-
-main = getArgs >>= parse
-
-parse ("--help":_) = putStrLn usage
-parse ("--version":_) = putStrLn "The Elm Server 0.1.1.7"
-parse [] = serve "/elm-mini.js"
-parse [arg]
-    | "--runtime-location=" `isPrefixOf` arg =
-        serve . tail $ dropWhile (/='=') arg
-    | otherwise = putStrLn usageMini
-parse _ = putStrLn usageMini
-
-usageMini =
-  "Usage: elm-server [OPTIONS]\n\
-  \Try `elm-server --help' for more information."
-
-usage =
-  "Usage: elm-server [OPTIONS]\n\
-  \Compiles and serves .elm files from the current directory.\n\
-  \Example: elm-server\n\
-  \\n\
-  \Resource Locations:\n\
-  \  --runtime-location   set the location of the Elm runtime (elm-mini.js)\n\
-  \\n\
-  \Compiler Information:\n\
-  \  --version            print the version information and exit\n\
-  \  --help               display this help and exit\n\
-  \\n\
-  \Elm home page: <http://elm-lang.org>"
diff --git a/src/Types/Constrain.hs b/src/Types/Constrain.hs
--- a/src/Types/Constrain.hs
+++ b/src/Types/Constrain.hs
@@ -1,77 +1,77 @@
-
-module Constrain where
-
-import Ast
-import Types
-import Data.List (foldl')
-import qualified Data.Set as Set
-import qualified Data.Map as Map
-import Control.Monad (liftM,mapM)
-import Control.Monad.State (evalState)
-import Guid
-
-data Constraint = Type :=: Type
-                | Type :<: Type
-                | Type :<<: Scheme
-                  deriving (Eq, Ord, Show)
-
-beta = VarT `liftM` guid
-unionA = Map.unionWith (++)
-unionsA = Map.unionsWith (++)
-
-constrain hints expr = do
-    (as,cs,t) <- inference expr
-    hs <- hints
-    let cMap = Map.intersectionWith (\t -> map (:<: t)) (Map.fromList hs) as
-    return $ Set.toList cs ++ (concat . map snd $ Map.toList cMap)
-
-inference (Var x) =
-    do b <- beta
-       return (Map.singleton x [b], Set.empty, b)
-inference (App e1 e2) =
-    do (a1,c1,t1) <- inference e1
-       (a2,c2,t2) <- inference e2
-       b <- beta
-       return ( unionA a1 a2
-              , Set.unions [c1,c2,Set.singleton $ t1 :=: (LambdaT t2 b)]
-              , b )
-inference (Lambda x e) =
-    do (a,c,t) <- inference e
-       b <- beta
-       return ( Map.delete x a
-              , Set.union c . Set.fromList . map (:=: b) $
-                          Map.findWithDefault [] x a
-              , LambdaT b t )
-inference (Let defs e) =
-    do (a,c,t) <- inference e
-       let (xs,es) = unzip defs
-       (as,cs,ts) <- unzip3 `liftM` mapM inference es
-       let assumptions = unionsA (a:as)
-       let f x t = map (:<: t) $ Map.findWithDefault [] x assumptions
-       let constraints = Set.fromList . concat $ zipWith f xs ts
-       return ( foldr Map.delete assumptions xs
-              , Set.unions $ c:constraints:cs
-              , t )
-
-inference (If e1 e2 e3) =
-    do (a1,c1,t1) <- inference e1
-       (a2,c2,t2) <- inference e2
-       (a3,c3,t3) <- inference e3
-       return ( unionsA [a1,a2,a3]
-              , Set.unions [c1,c2,c3, Set.fromList [ t1 :=: BoolT, t2 :=: t3 ] ]
-              , t2 )
-
-inference (Data name es) = inference $ foldl' App (Var name) es
-inference (Binop op e1 e2) = inference (Var op `App` e1 `App` e2)
-inference (Access (Var x) y) = inference . Var $ x ++ "." ++ y
-inference (Range e1 e2) = inference (Var "elmRange" `App` e1 `App` e2)
-
-inference other =
-    case other of
-      Number _ -> primitive IntT
-      Chr _ -> primitive CharT
-      Str _ -> primitive string
-      Boolean _ -> primitive BoolT
-      _ -> beta >>= primitive 
-
-primitive t = return (Map.empty, Set.empty, t)
+
+module Constrain where
+
+import Ast
+import Types
+import Data.List (foldl')
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import Control.Monad (liftM,mapM)
+import Control.Monad.State (evalState)
+import Guid
+
+data Constraint = Type :=: Type
+                | Type :<: Type
+                | Type :<<: Scheme
+                  deriving (Eq, Ord, Show)
+
+beta = VarT `liftM` guid
+unionA = Map.unionWith (++)
+unionsA = Map.unionsWith (++)
+
+constrain hints expr = do
+    (as,cs,t) <- inference expr
+    hs <- hints
+    let cMap = Map.intersectionWith (\t -> map (:<: t)) (Map.fromList hs) as
+    return $ Set.toList cs ++ (concat . map snd $ Map.toList cMap)
+
+inference (Var x) =
+    do b <- beta
+       return (Map.singleton x [b], Set.empty, b)
+inference (App e1 e2) =
+    do (a1,c1,t1) <- inference e1
+       (a2,c2,t2) <- inference e2
+       b <- beta
+       return ( unionA a1 a2
+              , Set.unions [c1,c2,Set.singleton $ t1 :=: (LambdaT t2 b)]
+              , b )
+inference (Lambda x e) =
+    do (a,c,t) <- inference e
+       b <- beta
+       return ( Map.delete x a
+              , Set.union c . Set.fromList . map (:=: b) $
+                          Map.findWithDefault [] x a
+              , LambdaT b t )
+inference (Let defs e) =
+    do (a,c,t) <- inference e
+       let (xs,es) = unzip defs
+       (as,cs,ts) <- unzip3 `liftM` mapM inference es
+       let assumptions = unionsA (a:as)
+       let f x t = map (:<: t) $ Map.findWithDefault [] x assumptions
+       let constraints = Set.fromList . concat $ zipWith f xs ts
+       return ( foldr Map.delete assumptions xs
+              , Set.unions $ c:constraints:cs
+              , t )
+
+inference (If e1 e2 e3) =
+    do (a1,c1,t1) <- inference e1
+       (a2,c2,t2) <- inference e2
+       (a3,c3,t3) <- inference e3
+       return ( unionsA [a1,a2,a3]
+              , Set.unions [c1,c2,c3, Set.fromList [ t1 :=: BoolT, t2 :=: t3 ] ]
+              , t2 )
+
+inference (Data name es) = inference $ foldl' App (Var name) es
+inference (Binop op e1 e2) = inference (Var op `App` e1 `App` e2)
+inference (Access (Var x) y) = inference . Var $ x ++ "." ++ y
+inference (Range e1 e2) = inference (Var "elmRange" `App` e1 `App` e2)
+
+inference other =
+    case other of
+      Number _ -> primitive IntT
+      Chr _ -> primitive CharT
+      Str _ -> primitive string
+      Boolean _ -> primitive BoolT
+      _ -> beta >>= primitive 
+
+primitive t = return (Map.empty, Set.empty, t)
diff --git a/src/Types/Types.hs b/src/Types/Types.hs
--- a/src/Types/Types.hs
+++ b/src/Types/Types.hs
@@ -1,58 +1,58 @@
-
-module Types where
-
-import Data.List (intercalate)
-import qualified Data.Set as Set
-
-type X = Int
-
-data Type = IntT
-          | StringT
-          | CharT
-          | BoolT
-          | LambdaT Type Type
-          | VarT X
-          | ADT String [Type]
-            deriving (Eq, Ord)
-
-data Scheme = Forall (Set.Set X) Type deriving (Eq, Ord, Show)
-
-element   = ADT "Element" []
-direction = ADT "Direction" []
-
-form  = ADT "Form" []
-line  = ADT "Line" []
-shape = ADT "Shape" []
-color = ADT "Color" []
-text  = ADT "List" [ADT "Text" []]
-point = tupleOf [IntT,IntT]
-
-listOf t   = ADT "List" [t]
-signalOf t = ADT "Signal" [t]
-tupleOf ts = ADT ("Tuple" ++ show (length ts)) ts
-string     = listOf CharT
-
-infixr ==>
-t1 ==> t2 = LambdaT t1 t2
-
-infix 8 -:
-name -: tipe = (,) name tipe
-
-hasType t = map (-: t)
-
-parens = ("("++) . (++")")
-
-instance Show Type where
-  show t =
-      case t of
-        { IntT -> "Int"
-        ; StringT -> "String"
-        ; CharT -> "Char"
-        ; BoolT -> "Bool"
-        ; LambdaT t1@(LambdaT _ _) t2 -> parens (show t1) ++ " -> " ++ show t2
-        ; LambdaT t1 t2 -> show t1 ++ " -> " ++ show t2
-        ; VarT x -> show x
-        ; ADT "List" [tipe] -> "[" ++ show tipe ++ "]"
-        ; ADT name [] -> name
-        ; ADT name cs -> parens $ name ++ " " ++ unwords (map show cs)
-        }
+
+module Types where
+
+import Data.List (intercalate)
+import qualified Data.Set as Set
+
+type X = Int
+
+data Type = IntT
+          | StringT
+          | CharT
+          | BoolT
+          | LambdaT Type Type
+          | VarT X
+          | ADT String [Type]
+            deriving (Eq, Ord)
+
+data Scheme = Forall (Set.Set X) Type deriving (Eq, Ord, Show)
+
+element   = ADT "Element" []
+direction = ADT "Direction" []
+
+form  = ADT "Form" []
+line  = ADT "Line" []
+shape = ADT "Shape" []
+color = ADT "Color" []
+text  = ADT "List" [ADT "Text" []]
+point = tupleOf [IntT,IntT]
+
+listOf t   = ADT "List" [t]
+signalOf t = ADT "Signal" [t]
+tupleOf ts = ADT ("Tuple" ++ show (length ts)) ts
+string     = listOf CharT
+
+infixr ==>
+t1 ==> t2 = LambdaT t1 t2
+
+infix 8 -:
+name -: tipe = (,) name tipe
+
+hasType t = map (-: t)
+
+parens = ("("++) . (++")")
+
+instance Show Type where
+  show t =
+      case t of
+        { IntT -> "Int"
+        ; StringT -> "String"
+        ; CharT -> "Char"
+        ; BoolT -> "Bool"
+        ; LambdaT t1@(LambdaT _ _) t2 -> parens (show t1) ++ " -> " ++ show t2
+        ; LambdaT t1 t2 -> show t1 ++ " -> " ++ show t2
+        ; VarT x -> show x
+        ; ADT "List" [tipe] -> "[" ++ show tipe ++ "]"
+        ; ADT name [] -> name
+        ; ADT name cs -> parens $ name ++ " " ++ unwords (map show cs)
+        }
diff --git a/src/Types/Unify.hs b/src/Types/Unify.hs
--- a/src/Types/Unify.hs
+++ b/src/Types/Unify.hs
@@ -1,71 +1,71 @@
-
-module Unify where
-
-import Constrain
-import Control.Arrow (second)
-import Control.Monad (liftM)
-import Data.List (foldl')
-import qualified Data.Set as Set
-import Guid
-import Types
-
-import Control.DeepSeq (NFData (..), deepseq)
-
-unify hints expr = run $ do
-  cs <- constrain hints expr
-  solver cs []
-
-solver [] subs = return $ Right subs
-
---------  Destruct Type-constructors  --------
-
-solver ((t1@(ADT n1 ts1) :=: t2@(ADT n2 ts2)) : cs) subs =
-    if n1 /= n2 then uniError t1 t2 else
-        solver (zipWith (:=:) ts1 ts2 ++ cs) subs
-solver ((LambdaT t1 t2 :=: LambdaT t1' t2') : cs) subs =
-    solver ([ t1 :=: t1', t2 :=: t2' ] ++ cs) subs
-
---------  Type-equality  --------
-
-solver ((VarT x :=: t) : cs) subs =
-    solver (map (cSub x t) cs) . map (second $ tSub x t) $ (x,t):subs
-solver ((t :=: VarT x) : cs) subs =
-    solver (map (cSub x t) cs) . map (second $ tSub x t) $ (x,t):subs
-solver ((t1 :=: t2) : cs) subs =
-    if t1 /= t2 then uniError t1 t2 else solver cs subs
-
---------  subtypes  --------
-
-solver ((t1 :<: t2) : cs) subs = do
-  let f x = do y <- guid ; return (x,VarT y)
-  pairs <- mapM f . Set.toList $ getVars t2
-  let t2' = foldr (uncurry tSub) t2 pairs
-  solver ((t1 :=: t2') : cs) subs
-
-
-cSub k v (t1 :=: t2) = force $ tSub k v t1 :=: tSub k v t2
-cSub k v (t1 :<: t2) = force $ tSub k v t1 :<: tSub k v t2
-
-tSub k v t@(VarT x) = if k == x then v else t
-tSub k v (LambdaT t1 t2) = force $ LambdaT (tSub k v t1) (tSub k v t2)
-tSub k v (ADT name ts) = ADT name (map (force . tSub k v) ts)
-tSub _ _ t = t
-
-getVars (VarT x)        = Set.singleton x
-getVars (LambdaT t1 t2) = Set.union (getVars t1) (getVars t2)
-getVars (ADT name ts)   = Set.unions $ map getVars ts
-getVars _               = Set.empty
-
-uniError t1 t2 =
-    return . Left $ "Type error: " ++ show t1 ++ " is not equal to " ++ show t2
-
-force x = x `deepseq` x
-
-instance NFData Constraint where
-  rnf (t1 :=: t2) = t1 `deepseq` t2 `deepseq` ()
-  rnf (t1 :<: t2) = t1 `deepseq` t2 `deepseq` ()
-
-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` ()
+
+module Unify where
+
+import Constrain
+import Control.Arrow (second)
+import Control.Monad (liftM)
+import Data.List (foldl')
+import qualified Data.Set as Set
+import Guid
+import Types
+
+import Control.DeepSeq (NFData (..), deepseq)
+
+unify hints expr = run $ do
+  cs <- constrain hints expr
+  solver cs []
+
+solver [] subs = return $ Right subs
+
+--------  Destruct Type-constructors  --------
+
+solver ((t1@(ADT n1 ts1) :=: t2@(ADT n2 ts2)) : cs) subs =
+    if n1 /= n2 then uniError t1 t2 else
+        solver (zipWith (:=:) ts1 ts2 ++ cs) subs
+solver ((LambdaT t1 t2 :=: LambdaT t1' t2') : cs) subs =
+    solver ([ t1 :=: t1', t2 :=: t2' ] ++ cs) subs
+
+--------  Type-equality  --------
+
+solver ((VarT x :=: t) : cs) subs =
+    solver (map (cSub x t) cs) . map (second $ tSub x t) $ (x,t):subs
+solver ((t :=: VarT x) : cs) subs =
+    solver (map (cSub x t) cs) . map (second $ tSub x t) $ (x,t):subs
+solver ((t1 :=: t2) : cs) subs =
+    if t1 /= t2 then uniError t1 t2 else solver cs subs
+
+--------  subtypes  --------
+
+solver ((t1 :<: t2) : cs) subs = do
+  let f x = do y <- guid ; return (x,VarT y)
+  pairs <- mapM f . Set.toList $ getVars t2
+  let t2' = foldr (uncurry tSub) t2 pairs
+  solver ((t1 :=: t2') : cs) subs
+
+
+cSub k v (t1 :=: t2) = force $ tSub k v t1 :=: tSub k v t2
+cSub k v (t1 :<: t2) = force $ tSub k v t1 :<: tSub k v t2
+
+tSub k v t@(VarT x) = if k == x then v else t
+tSub k v (LambdaT t1 t2) = force $ LambdaT (tSub k v t1) (tSub k v t2)
+tSub k v (ADT name ts) = ADT name (map (force . tSub k v) ts)
+tSub _ _ t = t
+
+getVars (VarT x)        = Set.singleton x
+getVars (LambdaT t1 t2) = Set.union (getVars t1) (getVars t2)
+getVars (ADT name ts)   = Set.unions $ map getVars ts
+getVars _               = Set.empty
+
+uniError t1 t2 =
+    return . Left $ "Type error: " ++ show t1 ++ " is not equal to " ++ show t2
+
+force x = x `deepseq` x
+
+instance NFData Constraint where
+  rnf (t1 :=: t2) = t1 `deepseq` t2 `deepseq` ()
+  rnf (t1 :<: t2) = t1 `deepseq` t2 `deepseq` ()
+
+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` ()
