diff --git a/Elm.cabal b/Elm.cabal
--- a/Elm.cabal
+++ b/Elm.cabal
@@ -1,5 +1,5 @@
 Name:                Elm
-Version:             0.8.0.3
+Version:             0.9
 Synopsis:            The Elm language module.
 Description:         Elm aims to make client-side web-development more pleasant.
                      It is a statically/strongly typed, functional reactive
@@ -21,132 +21,151 @@
 Build-type:          Custom
 
 Extra-source-files:  changelog.txt
-Data-files:          elm-runtime.js docs.json
-Cabal-version:       >=1.8
+Data-dir:            data
+Data-files:          elm-runtime.js interfaces.data
+Cabal-version:       >=1.9
 
 source-repository head
   type:     git
   location: git://github.com/evancz/Elm.git
 
 Library
-  exposed-modules:     Language.Elm,
-                       Language.Elm.Quasi
-  Hs-Source-Dirs:      compiler, compiler/Gen, compiler/Model, compiler/Transform
-  other-modules:       Ast,
-                       Context,
-                       CompileToJS,
-                       Cases,
-                       Substitute,
-                       ExtractNoscript,
-                       GenerateHtml,
-                       Guid,
-                       Libraries,
-                       LoadLibraries,
-                       Optimize,
+  exposed-modules:     Language.Elm
+  Hs-Source-Dirs:      compiler
+  other-modules:       Unique,
+                       SourceSyntax.Declaration,
+                       SourceSyntax.Expression,
+                       SourceSyntax.Everything,
+                       SourceSyntax.Helpers,
+                       SourceSyntax.Literal,
+                       SourceSyntax.Location,
+                       SourceSyntax.Module,
+                       SourceSyntax.Pattern,
+                       SourceSyntax.PrettyPrint,
+                       SourceSyntax.Type,
+                       Generate.JavaScript,
+                       Generate.Noscript,
+                       Generate.Html,
+                       Generate.Cases,
+                       Transform.Canonicalize,
+                       Transform.Check,
+                       Transform.SortDefinitions,
+                       Transform.Substitute,
+                       Transform.Optimize,
+                       Metadata.Prelude,
                        Initialize,
-                       Rename,
-                       Parse.Binops,
-                       Parse.Expr,
-                       Parse.Foreign,
-                       Parse.Library,
-                       Parse.Modules,
-                       Parse.Parser,
-                       Parse.Patterns,
-                       Parse.Types,
-                       Types.Alias,
-                       Types.Types,
-                       Types.Constrain,
-                       Types.Hints,
-                       Types.Solver,
-                       Types.Substitutions,
-                       Types.Unify,
+                       Parse.Binop,
+                       Parse.Declaration,
+                       Parse.Expression,
+                       Parse.Helpers,
+                       Parse.Literal,
+                       Parse.Module,
+                       Parse.Parse,
+                       Parse.Pattern,
+                       Parse.Type,
+                       Type.Constrain.Declaration,
+                       Type.Constrain.Expression,
+                       Type.Constrain.Literal,
+                       Type.Constrain.Pattern,
+                       Type.Environment,
+                       Type.Fragment,
+                       Type.Inference,
+                       Type.PrettyPrint,
+                       Type.Solve,
+                       Type.State,
+                       Type.Type,
+                       Type.Unify,
                        Paths_Elm
 
   Build-depends:       base >=4.2 && <5,
-                       containers >= 0.3,
-                       transformers >= 0.2,
-                       mtl >= 2,
-                       deepseq,
-                       parsec >= 3.1.1,
+                       binary,
                        blaze-html == 0.5.* || == 0.6.*,
                        blaze-markup == 0.5.1.*,
-                       text,
-                       shakespeare >= 1,
-                       template-haskell,
-                       pandoc >= 1.10,
                        bytestring,
+                       cmdargs,
+                       containers >= 0.3,
+                       directory,
+                       filepath,
                        hjsmin,
                        indents,
-                       filepath,
-                       json,
-                       directory
+                       mtl >= 2,
+                       pandoc >= 1.10,
+                       parsec >= 3.1.1,
+                       pretty,
+                       transformers >= 0.2,
+                       union-find,
+                       uniplate
 
 Executable elm
   Main-is:             Compiler.hs
-  Hs-Source-Dirs:      compiler, compiler/Gen, compiler/Model, compiler/Transform
-  extensions:          CPP
-  cpp-options:         -DELM_COMPILEDATADIR="dist/data"
-  other-modules:       Ast,
-                       Context,
-                       CompileToJS,
-                       Cases,
-                       Substitute,
-                       ExtractNoscript,
-                       GenerateHtml,
-                       Guid,
-                       Libraries,
-                       LoadLibraries,
-                       Optimize,
+  ghc-options:         -threaded -O2
+  Hs-Source-Dirs:      compiler
+  other-modules:       Unique,
+                       SourceSyntax.Declaration,
+                       SourceSyntax.Expression,
+                       SourceSyntax.Everything,
+                       SourceSyntax.Helpers,
+                       SourceSyntax.Literal,
+                       SourceSyntax.Location,
+                       SourceSyntax.Module,
+                       SourceSyntax.Pattern,
+                       SourceSyntax.PrettyPrint,
+                       SourceSyntax.Type,
+                       Generate.JavaScript,
+                       Generate.Noscript,
+                       Generate.Html,
+                       Generate.Cases,
+                       Transform.Canonicalize,
+                       Transform.Check,
+                       Transform.SortDefinitions,
+                       Transform.Substitute,
+                       Transform.Optimize,
+                       Metadata.Prelude,
                        Initialize,
-                       Rename,
-                       Parse.Binops,
-                       Parse.Expr,
-                       Parse.Foreign,
-                       Parse.Library,
-                       Parse.Modules,
-                       Parse.Parser,
-                       Parse.Patterns,
-                       Parse.Types,
-                       Types.Alias,
-                       Types.Types,
-                       Types.Constrain,
-                       Types.Hints,
-                       Types.Solver,
-                       Types.Substitutions,
-                       Types.Unify,
+                       Parse.Binop,
+                       Parse.Declaration,
+                       Parse.Expression,
+                       Parse.Helpers,
+                       Parse.Literal,
+                       Parse.Module,
+                       Parse.Parse,
+                       Parse.Pattern,
+                       Parse.Type,
+                       Type.Constrain.Declaration,
+                       Type.Constrain.Expression,
+                       Type.Constrain.Literal,
+                       Type.Constrain.Pattern,
+                       Type.Environment,
+                       Type.Fragment,
+                       Type.Inference,
+                       Type.PrettyPrint,
+                       Type.Solve,
+                       Type.State,
+                       Type.Type,
+                       Type.Unify,
                        Paths_Elm
 
   Build-depends:       base >=4.2 && <5,
-                       containers >= 0.3,
-                       transformers >= 0.2,
-                       mtl >= 2,
-                       deepseq,
-                       parsec >= 3.1.1,
+                       binary,
                        blaze-html == 0.5.* || == 0.6.*,
                        blaze-markup == 0.5.1.*,
-                       cmdargs,
-                       pandoc >= 1.10,
                        bytestring,
+                       cmdargs,
+                       containers >= 0.3,
+                       directory,
+                       filepath,
                        hjsmin,
                        indents,
-                       filepath,
-                       json,
-                       directory
-
-Executable elm-doc
-  Main-is:             Docs.hs
-  Hs-Source-Dirs:      compiler, compiler/Model, compiler/Transform
-  other-modules:       Ast,
-                       Context,
-                       Parse.Library,
-                       Parse.Modules,
-                       Rename
-
-  Build-depends:       base >=4.2 && <5,
-                       containers >= 0.3,
-                       transformers >= 0.2,
                        mtl >= 2,
-                       parsec >= 3.1.1,
                        pandoc >= 1.10,
-                       cmdargs,
-                       indents
+                       parsec >= 3.1.1,
+                       pretty,
+                       transformers >= 0.2,
+                       union-find,
+                       uniplate
+
+Test-Suite test-elm
+  Type:            exitcode-stdio-1.0
+  Hs-Source-Dirs:  tests
+  Main-is:         Everything.hs
+  build-depends:   base
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,2 +1,165 @@
 import Distribution.Simple
-main = defaultMain
+import Distribution.Simple.LocalBuildInfo
+import Distribution.Simple.Setup
+import Distribution.PackageDescription
+
+import System.Cmd
+import System.Directory
+import System.FilePath
+import System.IO
+import System.Process
+
+import Control.Monad
+import qualified Data.Binary as Binary
+import qualified Data.ByteString.Lazy as BS
+
+-- Part 1
+-- ------
+-- Add a build callout
+-- We need to build elm-doc and run it because that generates the file "docs.json"
+-- needs by Libraries.hs which is part of the elm library and executable
+-- Unfort. there seems to be no way to tell cabal that:
+--   (a) elm-doc generates docs.json, and
+--   (b) elm (library) depends on docs.json
+-- Therefore, we either use make instead (or a script), or hack around in cabal
+
+-- Part 2
+-- ------
+-- Add a post-build callout.
+-- We need to build the runtime.js after we've built elm (because we use elm to generate some of the JavaScript),
+-- but before cabal does the install file copy step
+
+-- Assumptions
+-- Elm.cabal expects the generated files to end up in dist/data
+-- git won't look in dist + cabal will clean it
+rtsDir :: LocalBuildInfo -> FilePath
+rtsDir lbi = "data"
+
+tempDir :: LocalBuildInfo -> FilePath
+tempDir lbi = "temp"
+
+-- The runtime is called:
+rts :: LocalBuildInfo -> FilePath
+rts lbi = rtsDir lbi </> "elm-runtime.js"
+
+-- The interfaces for the Standard Libraries live in:
+interfaces :: LocalBuildInfo -> FilePath
+interfaces lbi = rtsDir lbi </> "interfaces.data"
+
+-- buildDir with LocalBuildInfo points to "dist/build" (usually)
+elm lbi = buildDir lbi </> "elm" </> "elm"
+
+-- Care!  This appears to be based on an unstable API
+-- See: http://www.haskell.org/cabal/release/cabal-latest/doc/API/Cabal/Distribution-Simple.html#2
+
+
+main :: IO ()
+main = defaultMainWithHooks simpleUserHooks { postBuild = myPostBuild }
+
+
+-- Build
+
+-- note(1): We use to include docs.json directly into LoadLibraries at compile time
+-- If docs.json is used in other (template) haskell files, they should be copied
+-- and compiled in a separate directory (eg, dist/copiedSrc).
+-- This is to make sure they are re-compiled on docs.json changes.
+-- Copying is a better solution than 'touch'ing the source files
+-- (touch is non-portable and confusing wrt RCS).
+
+-- In the PackageDescription, the list of stuff to build is held in library
+-- (in a Maybe) and the executables list.  We want a PackageDescription that
+-- only mentions the executable 'name'
+filterExe :: String -> PackageDescription -> PackageDescription
+filterExe name pd = pd {
+    library = Nothing,
+    executables = filter (\x -> (exeName x == name)) (executables pd)
+    }
+
+-- It's not enough to fix the PackageDescription, we also have to fix the
+-- LocalBuildInfo. This includes the component build order (data ComponentName)
+-- which is horribly internal.
+filterLBI :: String -> LocalBuildInfo -> LocalBuildInfo
+filterLBI name lbi = lbi {
+    libraryConfig = Nothing,
+    compBuildOrder = [CExeName name],
+    executableConfigs = filter (\a -> (fst a == name)) (executableConfigs lbi)
+    }
+
+
+-- Post Build
+
+myPostBuild :: Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
+myPostBuild as bfs pd lbi = do
+    putStrLn "Custom build step: compiling standard libraries"
+    (elmos, elmis) <- compileLibraries lbi
+    putStrLn "Custom build step: build interfaces.data"
+    buildInterfaces lbi elmis
+    putStrLn "Custom build step: build elm-runtime.js"
+    buildRuntime lbi elmos
+    removeDirectoryRecursive (tempDir lbi)
+    postBuild simpleUserHooks as bfs pd lbi
+
+
+compileLibraries lbi = do
+  let temp = tempDir lbi                    -- temp
+      rts  = rtsDir  lbi                    -- data
+  createDirectoryIfMissing True temp
+  createDirectoryIfMissing True rts
+  out_c <- canonicalizePath temp            -- temp (root folder)
+  elm_c <- canonicalizePath (elm lbi)       -- dist/build/elm/elm
+  rtd_c <- canonicalizePath rts             -- data
+
+  let make file = do
+        -- replace 'system' call with 'runProcess' which handles args better
+        -- and allows env variable "Elm_datadir" which is used by LoadLibraries
+        -- to find docs.json
+        let args = [ "--only-js", "--make", "--no-prelude"
+                   , "--cache-dir="++out_c, "--build-dir="++out_c, file ]
+            arg = Just [("Elm_datadir", rtd_c)]
+        handle <- runProcess elm_c args Nothing arg Nothing Nothing Nothing
+        exitCode <- waitForProcess handle
+        return ( out_c </> replaceExtension file "elmo"
+               , out_c </> replaceExtension file "elmi")
+
+  setCurrentDirectory "libraries"
+  print =<< getCurrentDirectory
+  files <- getFiles ".elm" "."
+  files <- unzip `fmap` mapM make files
+  setCurrentDirectory ".."
+  return files
+
+buildInterfaces :: LocalBuildInfo -> [FilePath] -> IO ()
+buildInterfaces lbi elmis = do
+  createDirectoryIfMissing True (rtsDir lbi)
+  let ifaces = interfaces lbi
+  ifaceHandle <- openBinaryFile ifaces WriteMode
+  BS.hPut ifaceHandle (Binary.encode (length elmis))
+  let append file = do
+        handle <- openBinaryFile file ReadMode
+        bits <- hGetContents handle
+        length bits `seq` hPutStr ifaceHandle bits
+        hClose handle
+  mapM_ append elmis
+  hClose ifaceHandle
+
+buildRuntime :: LocalBuildInfo -> [FilePath] -> IO ()
+buildRuntime lbi elmos = do
+  createDirectoryIfMissing True (rtsDir lbi)
+  writeFile (rts lbi) "Elm = {}; Elm.Native = {}; Elm.Native.Graphics = {};\n\
+                      \Elm.Graphics = {}; ElmRuntime = {}; ElmRuntime.Render = {};\n"
+  mapM_ (appendJS lbi) =<< getFiles ".js" "libraries"
+  mapM_ (appendJS lbi) elmos
+  mapM_ (appendJS lbi) =<< getFiles ".js" "runtime"
+
+getFiles ext dir = do
+  contents <- map (dir </>) `fmap` getDirectoryContents dir
+  let files = filter (\f -> takeExtension f == ext) contents
+      dirs  = filter (not . hasExtension) contents
+  filess <- mapM (getFiles ext) dirs
+  return (files ++ concat filess)
+
+appendJS lbi file = do
+  putStrLn (dropExtension file)
+  str <- readFile file
+  length str `seq` return ()
+  appendFile (rts lbi) str
diff --git a/changelog.txt b/changelog.txt
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,4 +1,52 @@
 
+Release 0.9
+===========
+
+Build Improvements:
+  * Major speed improvements to type-checker
+  * Type-checker should catch _all_ type errors now
+  * Module-level compilation, only re-compile if necessary
+  * Import types and type aliases between modules
+  * Intermediate files are generated to avoid unneeded recompilation
+    and shorten compile time. These files go in ElmFiles/ by default
+  * Generated files are placed in ElmFiles/ by default, replicating
+    the directory structure of your source code.
+
+Error Messages:
+  * Cross-module type errors
+  * Errors for undefined values
+  * Pretty printing of expressions and types
+ 
+Syntax:
+  * Pattern matching on literals
+  * Pattern aliases with `as` (Andrew)
+  * Unary negation
+  * Triple-quoted multi-line strings
+  * Type annotations in let expressions (Andrew)
+  * Record Constructors
+  * Record type aliases can be closed on the zeroth column
+  * (,,) syntax in types
+  * Allow infix op definitions without args: (*) = add
+  * Unparenthesized if, let, case, lambda at end of binary expressions
+
+Libraries:
+  * Detect hovering over any Element
+  * Set alpha of arbitrary forms in collages
+  * Switch Text.height to use px instead of em
+
+Bug Fixes:
+  * Many bug fixes for collage, especially when rendering Elements.
+
+Website:
+  * Hot-swapping
+  * Much faster page load with pre-compiled Elm files (Max New)
+
+
+
+
+forgot to fill this in again...
+
+
 Release 0.7.2
 =============
 
diff --git a/compiler/Compiler.hs b/compiler/Compiler.hs
--- a/compiler/Compiler.hs
+++ b/compiler/Compiler.hs
@@ -1,91 +1,214 @@
 {-# LANGUAGE DeriveDataTypeable #-}
 module Main where
 
-import Data.Either (lefts, rights)
-import Data.List (intersect, intercalate,lookup)
-import Data.Maybe (fromMaybe)
+import Control.Monad
+import qualified Data.Map as Map
+import qualified Data.List as List
+import qualified Data.Binary as Binary
 import Data.Version (showVersion)
-import System.Console.CmdArgs
+import System.Console.CmdArgs hiding (program)
+import System.Directory
 import System.Exit
 import System.FilePath
-import Text.Blaze.Html.Renderer.String (renderHtml)
+import System.IO
+import GHC.Conc
 
+import qualified Text.Blaze.Html.Renderer.Pretty as Pretty
+import qualified Text.Blaze.Html.Renderer.String as Normal
 import qualified Text.Jasmine as JS
 import qualified Data.ByteString.Lazy.Char8 as BS
+import qualified Data.ByteString.Lazy as L
 
-import Ast
-import Initialize
-import CompileToJS
-import GenerateHtml
-import qualified Libraries as Libraries
+import qualified Metadata.Prelude as Prelude
+import qualified Transform.Canonicalize as Canonical
+import SourceSyntax.Module
+import Parse.Module (getModuleName)
+import Initialize (buildFromSource, getSortedDependencies)
+import Generate.JavaScript (jsModule)
+import Generate.Html (createHtml, JSStyle(..), JSSource(..))
 import Paths_Elm
 
-data ELM =
-    ELM { make :: Bool
-        , files :: [FilePath]
-        , runtime :: Maybe FilePath
-        , separate_js :: Bool
-        , only_js :: Bool
-        , import_js :: [FilePath]
-        , no_prelude :: Bool
-        , noscript :: Bool
-        , minify :: Bool
-	, output_directory :: Maybe FilePath
-        }
+import SourceSyntax.PrettyPrint (pretty, variable)
+import Text.PrettyPrint as P
+import qualified Type.Type as Type
+import qualified Data.Traversable as Traverse
+
+data Flags =
+    Flags { make :: Bool
+          , files :: [FilePath]
+          , runtime :: Maybe FilePath
+          , only_js :: Bool
+          , print_types :: Bool
+          , print_program :: Bool
+          , scripts :: [FilePath]
+          , no_prelude :: Bool
+          , minify :: Bool
+	  , cache_dir :: FilePath
+	  , build_dir :: FilePath
+          }
     deriving (Data,Typeable,Show,Eq)
 
-elm = ELM { make = False &= help "automatically compile dependencies."
-          , files = def &= args &= typ "FILES"
-          , runtime = Nothing &= typFile &=
-            help "Specify a custom location for Elm's runtime system."
-          , separate_js = False &= help "Compile to separate HTML and JS files."
-          , only_js = False &= help "Compile only to JavaScript."
-          , 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."
-          , no_prelude = False &= help "Do not import Prelude by default, used only when compiling standard libraries."
-          , 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")
+flags = Flags
+  { make = False
+           &= help "automatically compile dependencies."
+  , files = def &= args &= typ "FILES"
+  , runtime = Nothing &= typFile
+              &= help "Specify a custom location for Elm's runtime system."
+  , only_js = False
+              &= help "Compile only to JavaScript."
+  , print_types = False
+                  &= help "Print out infered types of top-level definitions."
+  , print_program = False
+                    &= help "Print out an internal representation of a program."
+  , scripts = [] &= typFile
+              &= help "Load JavaScript files in generated HTML. Files will be included in the given order."
+  , no_prelude = False
+                 &= help "Do not import Prelude by default, used only when compiling standard libraries."
+  , minify = False
+             &= help "Minify generated JavaScript and HTML"
+  , cache_dir = "cache" &= typFile
+                &= help "Directory for files cached to make builds faster. Defaults to cache/ directory."
+  , build_dir = "build" &= typFile
+                &= help "Directory for generated HTML and JS files. Defaults to build/ directory."
+  } &= help "Compile Elm programs to HTML, CSS, and JavaScript."
+    &= summary ("The Elm Compiler " ++ showVersion version ++ ", (c) Evan Czaplicki")
 
-main = do
-  args <- cmdArgs elm
-  mini <- getDataFileName "elm-runtime.js"
-  compileArgs mini args
+main :: IO ()             
+main = do setNumCapabilities =<< getNumProcessors
+          compileArgs =<< cmdArgs flags
 
-compileArgs mini flags =
-  case files flags of
-    [] -> putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
-    fs -> mapM_ (fileTo flags what loc) fs
-      where loc  = fromMaybe mini (runtime flags)
-            what | only_js flags = JS
-                 | separate_js flags = Split
-                 | otherwise = HTML
+compileArgs :: Flags -> IO ()
+compileArgs flags =
+    case files flags of
+      [] -> putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
+      fs -> mapM_ (build flags) fs
+          
 
-data What = JS | HTML | Split
+buildPath :: Flags -> FilePath -> String -> FilePath
+buildPath flags filePath ext = build_dir flags </> replaceExtension filePath ext
 
-fileTo flags what rtLoc file = do
-  let jsStyle  = if minify flags then Minified else Readable
-      formatJS = if minify flags then BS.unpack . JS.minify . BS.pack else id
-      prelude = not (no_prelude flags)
-  ems <- if make flags then build prelude file
-                       else do src <- readFile file
-                               return (fmap (:[]) (buildFromSource prelude src))
-  jss <- concat `fmap` mapM readFile (import_js flags)
-  case ems of
-    Left err -> do putStrLn $ "Error while compiling " ++ file ++ ":\n" ++ err
-                   exitFailure
-    Right ms' ->
-        let path = fromMaybe "" (output_directory flags) </> file
-            js = replaceExtension path ".js"
-            html = replaceExtension path ".html"
-            ms = if no_prelude flags then ms' else map Libraries.addPrelude ms'
-            txt = jss ++ concatMap jsModule ms
-        in  case what of
-              JS    -> writeFile js (formatJS txt)
-              HTML  -> writeFile html . renderHtml $
-                       modulesToHtml jsStyle "" rtLoc jss (noscript flags) ms
-              Split ->
-                  do writeFile html . renderHtml $ linkedHtml rtLoc js ms
-                     writeFile js (formatJS txt)
+cachePath :: Flags -> FilePath -> String -> FilePath
+cachePath flags filePath ext = cache_dir flags </> replaceExtension filePath ext
+
+elmo :: Flags -> FilePath -> FilePath
+elmo flags filePath = cachePath flags filePath "elmo"
+
+elmi :: Flags -> FilePath -> FilePath
+elmi flags filePath = cachePath flags filePath "elmi"
+
+
+buildFile :: Flags -> Int -> Int -> Interfaces -> FilePath -> IO (String,ModuleInterface)
+buildFile flags moduleNum numModules interfaces filePath =
+    do compiled <- alreadyCompiled
+       case compiled of
+         False -> compile
+         True -> do
+           handle <- openBinaryFile (elmi flags filePath) ReadMode
+           bits <- L.hGetContents handle
+           let info :: (String, ModuleInterface)
+               info = Binary.decode bits
+           L.length bits `seq` hClose handle
+           return info
+    where
+      alreadyCompiled :: IO Bool
+      alreadyCompiled = do
+        existsi <- doesFileExist (elmi flags filePath)
+        existso <- doesFileExist (elmo flags filePath)
+        if not existsi || not existso
+            then return False
+            else do tsrc <- getModificationTime filePath
+                    tint <- getModificationTime (elmo flags filePath)
+                    return (tsrc < tint)
+
+      number :: String
+      number = "[" ++ show moduleNum ++ " of " ++ show numModules ++ "]"
+
+      compile :: IO (String,ModuleInterface)
+      compile = do
+        source <- readFile filePath
+        let name = case getModuleName source of
+                     Just n -> n
+                     Nothing -> "Main"
+        putStrLn $ concat [ number, " Compiling ", name
+                          , replicate (max 1 (20 - length name)) ' '
+                          , "( " ++ filePath ++ " )" ]
+        
+        createDirectoryIfMissing True (cache_dir flags)
+        createDirectoryIfMissing True (build_dir flags)
+        metaModule <-
+            case buildFromSource (no_prelude flags) interfaces source of
+              Left errors -> do
+                  mapM print (List.intersperse (P.text " ") errors)
+                  exitFailure
+              Right modul -> do
+                  case print_program flags of
+                    False -> return ()
+                    True -> print . pretty $ program modul
+                  return modul
+        
+        if print_types flags then printTypes metaModule else return ()
+        tipes <- Traverse.traverse Type.toSrcType (types metaModule)
+        let interface = Canonical.interface name $ ModuleInterface {
+                          iTypes = tipes,
+                          iAdts = datatypes metaModule,
+                          iAliases = aliases metaModule
+                        }
+        createDirectoryIfMissing True . dropFileName $ elmi flags filePath
+        handle <- openBinaryFile (elmi flags filePath) WriteMode
+        L.hPut handle (Binary.encode (name,interface))
+        hClose handle
+        writeFile (elmo flags filePath) (jsModule metaModule)
+        return (name,interface)
+
+printTypes metaModule = do
+  putStrLn ""
+  forM_ (Map.toList $ types metaModule) $ \(n,t) -> do
+      pt <- Type.extraPretty t
+      print $ variable n <+> P.text ":" <+> pt
+  putStrLn ""
+
+getRuntime :: Flags -> IO FilePath
+getRuntime flags =
+    case runtime flags of
+      Just fp -> return fp
+      Nothing -> getDataFileName "elm-runtime.js"
+
+build :: Flags -> FilePath -> IO ()
+build flags rootFile = do
+  let noPrelude = no_prelude flags
+  files <- if make flags then getSortedDependencies noPrelude rootFile else return [rootFile]
+  let ifaces = if noPrelude then Map.empty else Prelude.interfaces
+  (moduleName, interfaces) <- buildFiles flags (length files) ifaces "" files
+  js <- foldM appendToOutput "" files
+  case only_js flags of
+    True -> do
+      putStr "Generating JavaScript ... "
+      writeFile (buildPath flags rootFile "js") (genJs js)
+      putStrLn "Done"
+    False -> do
+      putStr "Generating HTML ... "
+      runtime <- getRuntime flags
+      let html = genHtml $ createHtml runtime (takeBaseName rootFile) (sources js) moduleName ""
+          htmlFile = buildPath flags rootFile "html"
+      createDirectoryIfMissing True (takeDirectory htmlFile)
+      writeFile htmlFile html
+      putStrLn "Done"
+
+    where
+      appendToOutput :: String -> FilePath -> IO String
+      appendToOutput js filePath =
+          do src <- readFile (elmo flags filePath)
+             return (src ++ js)
+
+      genHtml = if minify flags then Normal.renderHtml else Pretty.renderHtml
+      genJs = if minify flags then BS.unpack . JS.minify . BS.pack else id
+      sources js = map Link (scripts flags) ++
+                   [ Source (if minify flags then Minified else Readable) js ]
+
+
+buildFiles :: Flags -> Int -> Interfaces -> String -> [FilePath] -> IO (String, Interfaces)
+buildFiles _ _ interfaces moduleName [] = return (moduleName, interfaces)
+buildFiles flags numModules interfaces _ (filePath:rest) = do
+  (name,interface) <- buildFile flags (numModules - length rest) numModules interfaces filePath
+  let interfaces' = Map.insert name interface interfaces
+  buildFiles flags numModules interfaces' name rest
diff --git a/compiler/Docs.hs b/compiler/Docs.hs
deleted file mode 100644
--- a/compiler/Docs.hs
+++ /dev/null
@@ -1,76 +0,0 @@
-
-module Main where
-
-import Ast
-import Control.Applicative ((<$>), (<*>))
-import Data.List (intercalate)
-import Data.Maybe (catMaybes)
-import Types.Types ((==>), Type ( ADT, VarT ) )
-import Parse.Types (datatype)
-import Parse.Library
-import Parse.Modules (moduleDef)
-import Text.Parsec hiding (newline,spaces)
-import System.Environment
-import System.Exit
-
-
-main = do
-  srcs <- mapM readFile =<< getArgs
-  case mapM docParse srcs of
-    Left err -> putStrLn err >> exitFailure
-    Right ms -> putStrLn (toModules ms)
-
-toModules ms = wrap (intercalate ",\n    " (map toModule ms))
-  where wrap s = "{ \"modules\" : [\n    " ++ s ++ "\n  ]\n}"
-
-toModule (name, values) =
-    "{ \"name\" : " ++ show name ++ ",\n      " ++
-    "\"values\" : [\n        " ++ vs ++ "\n      ]\n    }"
-  where vs = intercalate ",\n        " (map toValue values)
-
-toValue (name, tipe, desc) =
-    "{ \"name\" : " ++ show name ++
-    ",\n          \"type\" : " ++ show tipe ++
-    ",\n          \"desc\" : " ++ show desc ++ "\n        }"
-
-docParse :: String -> Either String (String, [(String, String, String)])
-docParse = setupParser $ do
-  optional freshLine
-  (names, exports) <- option (["Main"],[]) moduleDef
-  info <- many (try (annotation exports) <|> try skip <|> end)
-  return (intercalate "." names, concat info)
-    where
-      skip = manyTill anyChar simpleNewline >> return []
-      end  = many1 anyChar >> return []
-
-annotation :: [String] -> IParser [(String, String, String)]
-annotation exports =
-    do description <- comment
-       extras  <- option [] (lookAhead adt)
-       varName <- try typeDef <|> name
-       varType <- tipe
-       return $ extras ++ export varName varType description
-  where
-    comment = concatMap clip <$> many lineComment
-    clip str = case str of { ' ':rest -> rest ; _ -> str } ++ "\n"
-
-    name = do v <- lowVar <|> parens symOp
-              whitespace ; hasType ; whitespace ; return v
-
-    tipe = manyTill anyChar (try (simpleNewline >> notFollowedBy (string " ")))
-
-    export name tipe desc =
-        if null exports || name `elem` exports then [(name,tipe,desc)] else []
-
-    typeDef = lookAhead ((string "data" <|> string "type") >> whitespace >> capVar)
-
-    adt = do
-      (Datatype name tvs constructors) <- datatype
-      let toType (cName, typeArgs) =
-              (cName, show $ foldr (==>) (ADT name $ map VarT tvs) typeArgs, "")
-      return $ map toType constructors
-
-setupParser p source =
-    case iParse p "" source of
-      Right result -> Right result
-      Left err -> Left $ "Parse error at " ++ show err
diff --git a/compiler/Gen/Cases.hs b/compiler/Gen/Cases.hs
deleted file mode 100644
--- a/compiler/Gen/Cases.hs
+++ /dev/null
@@ -1,87 +0,0 @@
-
-module Cases (caseToMatch, Match (..), Clause (..), matchSubst) where
-
-import Control.Arrow (first)
-import Control.Monad (liftM,foldM)
-import Data.List (groupBy,sortBy,lookup)
-import Data.Maybe (fromMaybe)
-
-import Ast
-import Context
-import Guid
-import Substitute
-
-caseToMatch patterns = do
-  v <- newVar
-  match [v] (map (first (:[])) patterns) Fail
-
-newVar = do n <- guid
-            return $ "case" ++ show n
-
-data Match = Match String [Clause] Match
-           | Break
-           | Fail
-           | Other CExpr
-           | Seq [Match]
-             deriving Show
-
-data Clause = Clause String [String] Match
-              deriving Show
-
-matchSubst :: [(String,String)] -> Match -> Match
-matchSubst _ Break = Break
-matchSubst _ Fail = Fail
-matchSubst pairs (Seq ms) = Seq (map (matchSubst pairs) ms)
-matchSubst pairs (Other (C t s e)) =
-    Other . C t s $ foldr ($) e $ map (\(x,y) -> subst x (Var y)) pairs
-matchSubst pairs (Match n cs m) =
-    Match (varSubst n) (map clauseSubst cs) (matchSubst pairs m)
-        where varSubst v = fromMaybe v (lookup v pairs)
-              clauseSubst (Clause c vs m) =
-                  Clause c (map varSubst vs) (matchSubst pairs m)
-
-isCon (PData _ _ : _, _) = True
-isCon _                  = False
-
-isVar p = not (isCon p)
-
-match :: [String] -> [([Pattern],CExpr)] -> Match -> GuidCounter Match
-match [] [] def = return def
-match [] [([],e)] Fail  = return $ Other e
-match [] [([],e)] Break = return $ Other e
-match [] cs def = return $ Seq (map (Other . snd) cs ++ [def])
-match vs cs def
-    | all isVar cs = matchVar vs cs def
-    | all isCon cs = matchCon vs cs def
-    | otherwise    = matchMix vs cs def
-
-matchVar :: [String] -> [([Pattern],CExpr)] -> Match -> GuidCounter Match
-matchVar (v:vs) cs def = match vs (map subVar cs) def
-  where
-    subVar (p:ps, ce@(C t s e)) =
-        let ctx = C t s in
-        (ps, case p of
-               PVar x     -> C t s $ subst x (Var v) e
-               PAnything  -> ce
-               PRecord fs ->
-                   ctx $ foldr (\x -> subst x (Access (ctx (Var v)) x)) e fs
-        )
-
-matchCon :: [String] -> [([Pattern],CExpr)] -> Match -> GuidCounter Match
-matchCon (v:vs) cs def = (flip (Match v) def) `liftM` mapM toClause css
-    where css = groupBy (withName (==)) $ sortBy (withName compare) cs
-          withName f (PData n1 _:_,_) (PData n2 _:_,_) = f n1 n2
-          toClause cs = let (PData name _ : _ , _) = head cs in
-                        matchClause name (v:vs) cs Break
-
-matchClause :: String -> [String] -> [([Pattern],CExpr)] -> Match -> GuidCounter Clause
-matchClause c (v:vs) cs def =
-    do vs' <- getVars
-       Clause c vs' `liftM` match (vs' ++ vs) (map flatten cs) def
-    where flatten (PData _ ps' : ps, e) = (ps' ++ ps, e)
-          getVars = let (PData _ ps : _, _) = head cs in
-                    mapM (\_ -> newVar) ps
-
-matchMix :: [String] -> [([Pattern],CExpr)] -> Match -> GuidCounter Match
-matchMix vs cs def = foldM (flip $ match vs) def (reverse css)
-    where css = groupBy (\p1 p2 -> isCon p1 == isCon p2) cs
diff --git a/compiler/Gen/CompileToJS.hs b/compiler/Gen/CompileToJS.hs
deleted file mode 100644
--- a/compiler/Gen/CompileToJS.hs
+++ /dev/null
@@ -1,339 +0,0 @@
-module CompileToJS (showErr, jsModule) where
-
-import Control.Arrow (first,second)
-import Control.Monad (liftM,(<=<),join,ap)
-import Data.Char (isAlpha,isDigit)
-import Data.List (intercalate,sortBy,inits,foldl')
-import qualified Data.Map as Map
-import Data.Either (partitionEithers)
-import qualified Text.Pandoc as Pan
-
-import Ast
-import Context
-import Rename (derename)
-import Cases
-import Guid
-import Rename (deprime)
-import Types.Types ( Type(RecordT) )
-
-showErr :: String -> String
-showErr err = globalAssign "Elm.Main" (jsFunc "elm" body)
-    where msg = show . concatMap (++"<br>") . lines $ err
-          body = "var T = Elm.Text(elm);\n\
-                 \return { main : T.text(T.monospace(" ++ msg ++ ")) };"
-
-indent = concatMap f
-    where f '\n' = "\n  "
-          f c = [c]
-
-internalImports =
-    [ ("N" , "Elm.Native"),
-      ("_N", "N.Utils(elm)"),
-      ("_L", "N.List(elm)"),
-      ("_E", "N.Error(elm)"),
-      ("_str", "N.JavaScript(elm).toString")
-    ]
-
-parens s  = "(" ++ s ++ ")"
-brackets s  = "{" ++ s ++ "}"
-jsObj = brackets . intercalate ", "
-jsList ss = "["++ intercalate "," ss ++"]"
-jsFunc args body = "function(" ++ args ++ "){" ++ indent body ++ "}"
-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]
-
-globalAssign n e = "\n" ++ assign' n e ++ ";"
-assign' n e = n ++ " = " ++ e
-
-jsModule (Module names exports imports stmts) =
- setup ("Elm":modNames) ++ globalAssign ("Elm." ++ modName) (jsFunc "elm" program)
-  where
-    modNames = if null names then ["Main"] else names
-    modName  = intercalate "." modNames
-    includes = concatMap jsImport imports
-    body = stmtsToJS stmts
-    defs = assign "$op" "{}"
-    program = "\nvar " ++ usefulFuncs ++ ";" ++ defs ++ includes ++ body ++
-              setup ("elm":"Native":modNames) ++
-              assign "_" ("elm.Native." ++ modName ++ "||{}") ++
-              getExports exports stmts ++ setup ("elm":modNames) ++
-              ret (assign' ("elm." ++ modName) "_") ++ "\n"
-    setup modNames = concatMap (\n -> globalAssign n $ n ++ "||{}") .
-                     map (intercalate ".") . drop 2 . inits $ init modNames
-    usefulFuncs = intercalate ", " (map (uncurry assign') internalImports)
-
-getExports names stmts = "\n"++ 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 = "++) . jsObj $ 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 _ _ _   -> []
-                            TypeAlias _ _ _     -> []
-                            TypeAnnotation _ _  -> []
-
-
-jsImport (modul, how) =
-    case how of
-      As name -> assign name ("Elm." ++ modul ++ parens "elm")
-      Hiding vs -> include ++ " var hiding=" ++ (jsObj $ map (++":1") vs) ++
-                   "; for(var k in _){if(k in hiding)continue;" ++
-                   "eval('var '+k+'=_[\"'+k+'\"]')}"
-      Importing vs -> include ++ named
-          where 
-            imprt v = assign' v ("_." ++ v)
-            def (o:p) = imprt (if isOp o then "$op['" ++ o:p ++ "']" else deprime (o:p))
-            named = if null vs then "" else "\nvar " ++ intercalate ", " (map def vs) ++ ";"
-  where
-    include = "\nvar _ = Elm." ++ modul ++ parens "elm" ++ ";" ++ setup modul
-    setup moduleName = " var " ++ concatMap (++";") (defs ++ [assign' moduleName "_"])
-        where
-          defs = map (\n -> assign' n (n ++ "||{}")) (subnames moduleName)
-          subnames = map (intercalate ".") . tail . inits . init . split
-          split names = case go [] names of
-                          (name, []) -> [name]
-                          (name, ns) -> name : split ns
-          go name str = case str of
-                          '.':rest -> (reverse name, rest)
-                          c:rest   -> go (c:name) rest
-                          []       -> (reverse name, [])
-
-
-
-stmtsToJS :: [Statement] -> String
-stmtsToJS stmts = run $ do program <- mapM toJS (sortBy cmpStmt stmts)
-                           return (concat program)
-    where
-      cmpStmt s1 s2 = compare (valueOf s1) (valueOf s2)
-      valueOf s = case s of
-                    Datatype _ _ _             -> 1
-                    ImportEvent _ _ _ _        -> 2
-                    Definition (FnDef f [] _)  ->
-                        if derename f == "main" then 5 else 4
-                    Definition _               -> 3
-                    ExportEvent _ _ _          -> 6
-                    TypeAlias _ _ _            -> 0
-                    TypeAnnotation _ _         -> 0
-
-class ToJS a where
-  toJS :: a -> GuidCounter String
-
-instance ToJS Def where
-  toJS (FnDef x [] e) = assign x `liftM` toJS' e
-  toJS (FnDef f as e) = (assign f . wrapper . func) `liftM` toJS' e
-      where
-        func body = jsFunc (intercalate ", " as) (ret body)
-        wrapper e | length as == 1 = e
-                  | otherwise = 'F' : show (length as) ++ parens e
-  toJS (OpDef op a1 a2 e) =
-      do body <- toJS' e                    
-         let func = "F2" ++ parens (jsFunc (a1 ++ ", " ++ a2) (ret body))
-         return (globalAssign ("$op['" ++ op ++ "']") func)
-
-instance ToJS Statement where
-  toJS stmt =
-    case stmt of
-      Definition d -> toJS d
-      Datatype _ _ tcs -> concat `liftM` mapM (toJS . toDef) tcs
-          where toDef (name,args) =
-                    let vars = map (('a':) . show) [1..length args] in
-                    Definition . FnDef name vars . noContext $
-                    Data (derename name) (map (noContext . Var) vars)
-      ImportEvent js base elm _ ->
-        do v <- toJS' base
-           return $ concat [ "\nvar " ++ elm ++ "=Elm.Signal(elm).constant(" ++ v ++ ");"
-                           , "\ndocument.addEventListener('", js
-                           , "_' + elm.id, function(e) { elm.notify(", elm
-                           , ".id, e.value); });" ]
-      ExportEvent js elm _ ->
-        return $ concat [ "\nlift(function(v) { "
-                        , "var e = document.createEvent('Event');"
-                        , "e.initEvent('", js, "_' + elm.id, true, true);"
-                        , "e.value = v;"
-                        , "document.dispatchEvent(e); return v; })(", elm, ");" ]
-      TypeAnnotation _ _ -> return ""
-      TypeAlias n _ t -> return ""
-
-toJS' :: CExpr -> GuidCounter String
-toJS' (C txt span expr) =
-    case expr of
-      MultiIf ps -> multiIfToJS span ps
-      Case e cases -> caseToJS span e cases
-      _ -> toJS expr
-
-remove x e = "_N.remove('" ++ x ++ "', " ++ e ++ ")"
-addField x v e = "_N.insert('" ++ x ++ "', " ++ v ++ ", " ++ e ++ ")"
-setField fs e = "_N.replace(" ++ jsList (map f fs) ++ ", " ++ e ++ ")"
-    where f (x,v) = "['" ++ x ++ "'," ++ v ++ "]"
-access x e = e ++ "." ++ x
-makeRecord kvs = record `liftM` collect kvs
-  where
-    combine r (k,v) = Map.insertWith (++) k v r
-    collect = liftM (foldl' combine Map.empty) . mapM prep
-    prep (k, as, e@(C t s _)) =
-        do v <- toJS' (foldr (\x e -> C t s $ Lambda x e) e as)
-           return (k,[v])
-    fields fs =
-        brackets ("\n  "++intercalate ",\n  " (map (\(k,v) -> k++":"++v) fs))
-    hidden = fields . map (second jsList) .
-             filter (not . null . snd) . Map.toList . Map.map tail
-    record kvs = fields . (("_", hidden kvs) :) . Map.toList . Map.map head $ kvs
-
-
-instance ToJS Expr where
- toJS expr =
-  case expr of
-    Var x -> return $ x
-    Chr c -> return $ quoted [c]
-    Str s -> return $ "_str" ++ parens (quoted s)
-    IntNum   n -> return $ show n
-    FloatNum n -> return $ show n
-    Boolean  b -> return $ if b then "true" else "false"
-    Range lo hi -> jsRange `liftM` toJS' lo `ap` toJS' hi
-    Access e x -> access x `liftM` toJS' e
-    Remove e x -> remove x `liftM` toJS' e
-    Insert e x v -> addField x `liftM` toJS' v `ap` toJS' e
-    Modify e fs -> do fs' <- (mapM (\(x,v) -> (,) x `liftM` toJS' v) fs)
-                      setField fs' `liftM` toJS' e
-    Record fs -> makeRecord fs
-    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 e1 e2 -> jsApp e1 e2
-    Let defs e -> jsLet defs e
-    Data name es ->
-        do fs <- mapM toJS' es
-           return $ case name of
-              "Nil" -> jsNil
-              "Cons" -> jsCons (head fs) ((head . tail) fs)
-              _ -> jsObj $ ("ctor:" ++ show name) : fields
-                   where fields = zipWith (\n e -> "_" ++ show n ++ ":" ++ e) [0..] fs
-
-    Markdown doc -> return $ "text('" ++ pad ++ md ++ pad ++ "')"
-        where pad = "<div style=\"height:0;width:0;\">&nbsp;</div>"
-              md = formatMarkdown $ Pan.writeHtmlString Pan.def doc
-
-jsApp e1 e2 =
-    do f  <- toJS' func
-       as <- mapM toJS' args
-       return $ case as of
-                  [a] -> f ++ parens a
-                  _   -> "A" ++ show (length as) ++ parens (intercalate ", " (f:as))
-  where
-    (func, args) = go [e2] e1
-    go args e =
-       case e of
-         (C _ _ (App e1 e2)) -> go (e2 : args) e1
-         _ -> (e, args)
-
-formatMarkdown = concatMap f
-    where f '\'' = "\\'"
-          f '\n' = "\\n"
-          f '"'  = "\""
-          f c = [c]
-
-multiIfToJS span ps =
-    case last ps of
-      (C _ _ (Var "otherwise"), e) -> toJS' e >>= \b -> format b (init ps)
-      _ -> format ("_E.If" ++ parens (quoted (show span))) ps
-  where
-    format base ps =
-        foldr (\c e -> parens $ c ++ " : " ++ e) base `liftM` mapM f ps
-    f (b,e) = do b' <- toJS' b
-                 e' <- toJS' e
-                 return (b' ++ " ? " ++ e')
-
-jsLet defs e' = do ds <- jsDefs defs
-                   e <- toJS' e'
-                   return $ jsFunc "" (concat ds ++ ret e) ++ "()"
-  where 
-    jsDefs defs = mapM toJS (sortBy f defs)
-    f a b = compare (valueOf a) (valueOf b)
-    valueOf (FnDef _ [] _) = 2
-    valueOf (FnDef _ _ _) = 1
-    valueOf (OpDef _ _ _ _)  = 1
-
-caseToJS span e ps = do
-  match <- caseToMatch ps
-  e' <- toJS' e
-  let (match',stmt) = case (match,e) of
-        (Match name _ _, C _ _ (Var x)) -> (matchSubst [(name,x)] match, "")
-        (Match name _ _, _)             -> (match, assign name e')
-        _                               -> (match, "")
-  matches <- matchToJS span match'
-  return $ "function(){ " ++ stmt ++ matches ++ " }()"
-
-matchToJS span match =
-  case match of
-    Match name clauses def ->
-        do cases <- concat `liftM` mapM (clauseToJS span name) clauses
-           finally <- matchToJS span def
-           return $ concat [ "\nswitch (", name, ".ctor) {",
-                             indent cases, "\n}", finally ]
-    Fail -> return ("_E.Case" ++ parens (quoted (show span)))
-    Break -> return "break;"
-    Other e -> ret `liftM` toJS' e
-    Seq ms -> concat `liftM` mapM (matchToJS span) (dropEnd [] ms)
-        where
-          dropEnd acc [] = acc
-          dropEnd acc (m:ms) =
-              case m of
-                Other _ -> acc ++ [m]
-                _ -> dropEnd (acc ++ [m]) ms
-
-clauseToJS span var (Clause name vars e) = do
-  let vars' = map (\n -> var ++ "._" ++ show n) [0..]
-  s <- matchToJS span $ matchSubst (zip vars vars') e
-  return $ concat [ "\ncase ", quoted name, ":", indent s ]
-
-jsNil         = "_L.Nil"
-jsCons  e1 e2 = "_L.Cons(" ++ e1 ++ "," ++ e2 ++ ")"
-jsRange e1 e2 = "_L.range" ++ parens (e1 ++ "," ++ e2)
-jsCompare e1 e2 op = parens ("_N.cmp(" ++ e1 ++ "," ++ e2 ++ ").ctor" ++ op)
-
-binop (o:p) e1 e2
-    | isAlpha o || '_' == o = (o:p) ++ parens e1 ++ parens e2
-    | otherwise =
-        let ops = ["+","-","*","/","&&","||"] in
-        case o:p of
-          "::" -> jsCons e1 e2
-          "++" -> "_L.append" ++ parens (e1 ++ "," ++ e2)
-          "$"  -> e1 ++ parens e2
-          "<|" -> e1 ++ parens e2
-          "|>" -> e2 ++ parens e1
-          "."  -> jsFunc "x" . ret $ e1 ++ parens (e2 ++ parens "x")
-          "^"  -> "Math.pow(" ++ e1 ++ "," ++ e2 ++ ")"
-          "==" -> "_N.eq(" ++ e1 ++ "," ++ e2 ++ ")"
-          "/=" -> "!_N.eq(" ++ e1 ++ "," ++ e2 ++ ")"
-          "<"  -> jsCompare e1 e2 "==='LT'"
-          ">"  -> jsCompare e1 e2 "==='GT'"
-          "<=" -> jsCompare e1 e2 "!=='GT'"
-          ">=" -> jsCompare e1 e2 "!=='LT'"
-          "<~" -> "A2(lift," ++ e1 ++ "," ++ e2 ++ ")"
-          "~"  -> "A3(lift2,F2(function(f,x){return f(x)}),"++e1++","++e2++")"
-          _  | elem (o:p) ops -> parens (e1 ++ (o:p) ++ e2)
-             | otherwise      -> concat [ "$op['", o:p, "']"
-                                        , parens e1, parens e2 ]
diff --git a/compiler/Gen/ExtractNoscript.hs b/compiler/Gen/ExtractNoscript.hs
deleted file mode 100644
--- a/compiler/Gen/ExtractNoscript.hs
+++ /dev/null
@@ -1,59 +0,0 @@
-
-module ExtractNoscript (extractNoscript) where
-
-import Ast
-import Context
-import qualified Text.Pandoc as Pan
-
-extractNoscript :: Module -> String
-extractNoscript modul = concat (extract modul)
-
-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 e => Extract (Context e) where
-  extract (C _ _ 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 (C _ _ (App (C _ _ (Var "link")) src)) txt -> linkExtract src txt
-      App (C _ _ (App (C _ _ (Var "Text.link")) src)) txt -> linkExtract src txt
-      App (C _ _ (Var "header")) e -> tag "h1" e
-      App (C _ _ (Var "bold")) e -> tag "b" e
-      App (C _ _ (Var "italic")) e -> tag "i" e
-      App (C _ _ (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 extract defs ++ f e
-      Var _ -> []
-      Case e cases -> concatMap (f . snd) cases
-      Data _ es -> concatMap f es
-      Markdown doc -> [ Pan.writeHtmlString Pan.def doc ]
-      _ -> []
-
-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/compiler/Gen/GenerateHtml.hs b/compiler/Gen/GenerateHtml.hs
deleted file mode 100644
--- a/compiler/Gen/GenerateHtml.hs
+++ /dev/null
@@ -1,75 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module GenerateHtml (generateHtml,
-                     modulesToHtml, linkedHtml,
-                     JSStyle (..)
-                    ) where
-
-import Data.List (intercalate)
-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
-
-import Text.Jasmine (minify)
-import qualified Data.ByteString.Lazy.Char8 as BS
-
-import Ast
-import Initialize (buildFromSource)
-import CompileToJS
-import ExtractNoscript
-import Libraries as Libraries
-
-data JSStyle = Minified | Readable
-
-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
-    where content = case jsStyle of 
-                      Minified -> BS.unpack . minify . BS.pack $ s
-                      Readable -> 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-runtime.js as expected by the browser
-             -> String -- ^ The page title
-             -> String -- ^ The elm source code.
-             -> Html
-generateHtml libLoc title source =
-  case buildFromSource True source of
-    Right modul -> modulesToHtml Readable title libLoc [] True [modul]
-    Left err -> createHtml Readable libLoc title (Right $ showErr err)
-                (H.noscript "") "Main"
-
-
-modulesToHtml jsStyle title libLoc jss nscrpt modules =
-  createHtml jsStyle libLoc title' js noscript altTitle
-    where
-      js = Right $ jss ++ concatMap jsModule modules
-      noscript = if nscrpt then extractNoscript $ last modules else ""
-      title' = if null title then altTitle else title
-      altTitle = intercalate "." names
-          where Module names _ _ _ = last modules
-                  
-
-linkedHtml rtLoc jsLoc modules =
-    createHtml Readable rtLoc title (Left jsLoc) (H.noscript "") title
-    where
-      title = (\(Module names _ _ _) -> intercalate "." names) (last modules)
-
-
-createHtml jsStyle libLoc title js noscript moduleToLoad =
-    H.docTypeHtml $ do 
-      H.head $ do
-        H.meta ! A.charset "UTF-8"
-        H.title . H.toHtml $ title
-        makeScript Readable (Left libLoc)
-        makeScript jsStyle js
-      H.body $ do
-        H.script ! A.type_ "text/javascript" $ preEscapedToMarkup ("Elm.fullscreen(Elm." ++ moduleToLoad ++ ")" :: String)
-        H.noscript $ preEscapedToMarkup noscript
diff --git a/compiler/Generate/Cases.hs b/compiler/Generate/Cases.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Generate/Cases.hs
@@ -0,0 +1,128 @@
+module Generate.Cases (caseToMatch, Match (..), Clause (..), matchSubst) where
+
+import Control.Arrow (first)
+import Control.Monad (liftM,foldM)
+import Data.List (groupBy,sortBy,lookup)
+import Data.Maybe (fromMaybe)
+
+import Unique
+import SourceSyntax.Location
+import SourceSyntax.Literal
+import SourceSyntax.Pattern
+import SourceSyntax.Expression
+import Transform.Substitute
+
+caseToMatch patterns = do
+  v <- newVar
+  (,) v `liftM` match [v] (map (first (:[])) patterns) Fail
+
+newVar = do n <- guid
+            return $ "case" ++ show n
+
+data Match t v
+    = Match String [Clause t v] (Match t v)
+    | Break
+    | Fail
+    | Other (LExpr t v)
+    | Seq [Match t v]
+      deriving Show
+
+data Clause t v =
+    Clause (Either String Literal) [String] (Match t v)
+    deriving Show
+
+matchSubst :: [(String,String)] -> Match t v -> Match t v
+matchSubst _ Break = Break
+matchSubst _ Fail = Fail
+matchSubst pairs (Seq ms) = Seq (map (matchSubst pairs) ms)
+matchSubst pairs (Other (L s e)) =
+    Other . L s $ foldr ($) e $ map (\(x,y) -> subst x (Var y)) pairs
+matchSubst pairs (Match n cs m) =
+    Match (varSubst n) (map clauseSubst cs) (matchSubst pairs m)
+        where varSubst v = fromMaybe v (lookup v pairs)
+              clauseSubst (Clause c vs m) =
+                  Clause c (map varSubst vs) (matchSubst pairs m)
+
+isCon (p:ps, e) =
+  case p of
+    PData _ _  -> True
+    PLiteral _ -> True
+    _          -> False
+
+isVar p = not (isCon p)
+
+match :: [String] -> [([Pattern],LExpr t v)] -> Match t v -> Unique (Match t v)
+match [] [] def = return def
+match [] [([],e)] Fail  = return $ Other e
+match [] [([],e)] Break = return $ Other e
+match [] cs def = return $ Seq (map (Other . snd) cs ++ [def])
+match vs@(v:_) cs def
+    | all isVar cs' = matchVar vs cs' def
+    | all isCon cs' = matchCon vs cs' def
+    | otherwise     = matchMix vs cs' def
+  where
+    cs' = map (dealias v) cs
+
+dealias v c@(p:ps, L s e) =
+    case p of
+      PAlias x pattern -> (pattern:ps, L s $ subst x (Var v) e)
+      _ -> c
+
+matchVar :: [String] -> [([Pattern],LExpr t v)] -> Match t v
+         -> Unique (Match t v)
+matchVar (v:vs) cs def = match vs (map subVar cs) def
+  where
+    subVar (p:ps, ce@(L s e)) = (ps, L s $ subOnePattern p e)
+        where
+          subOnePattern pattern e =
+            case pattern of
+              PVar x     -> subst x (Var v) e
+              PAnything  -> e
+              PRecord fs ->
+                 foldr (\x -> subst x (Access (L s (Var v)) x)) e fs
+
+matchCon :: [String] -> [([Pattern],LExpr t v)] -> Match t v
+         -> Unique (Match t v)
+matchCon (v:vs) cs def = (flip (Match v) def) `liftM` mapM toClause css
+    where
+      css = groupBy eq (sortBy cmp cs)
+
+      cmp (p1:_,_) (p2:_,_) =
+        case (p1,p2) of
+          (PData n1 _, PData n2 _) -> compare n1 n2
+          _ -> compare p1 p2
+
+      eq (p1:_,_) (p2:_,_) =
+        case (p1,p2) of
+          (PData n1 _, PData n2 _) -> n1 == n2
+          _ -> p1 == p2
+
+      toClause cs =
+        case head cs of
+          (PData name _ : _, _) -> matchClause (Left name) (v:vs) cs Break
+          (PLiteral lit : _, _) -> matchClause (Right lit) (v:vs) cs Break
+
+matchClause :: Either String Literal
+            -> [String]
+            -> [([Pattern],LExpr t v)]
+            -> Match t v
+            -> Unique (Clause t v)
+matchClause c (v:vs) cs def =
+    do vs' <- getVars
+       Clause c vs' `liftM` match (vs' ++ vs) (map flatten cs) def
+    where
+
+      flatten (p:ps, e) =
+          case p of
+            PData _ ps' -> (ps' ++ ps, e)
+            PLiteral _  -> (ps, e)
+
+      getVars =
+          case head cs of
+            (PData _ ps : _, _) -> mapM (\_ -> newVar) ps
+            (PLiteral _ : _, _) -> return []
+
+matchMix :: [String] -> [([Pattern],LExpr t v)] -> Match t v
+         -> Unique (Match t v)
+matchMix vs cs def = foldM (flip $ match vs) def (reverse css)
+    where css = groupBy (\p1 p2 -> isCon p1 == isCon p2) cs
diff --git a/compiler/Generate/Html.hs b/compiler/Generate/Html.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Generate/Html.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Generate.Html
+    (generateHtml,
+     createHtml,
+     JSStyle (..),
+     JSSource (..)
+    ) where
+
+import Text.Blaze (preEscapedToMarkup)
+import qualified Text.Blaze.Html5 as H
+import Text.Blaze.Html5 ((!))
+import qualified Text.Blaze.Html5.Attributes as A
+
+import Text.Jasmine (minify)
+import qualified Data.ByteString.Lazy.Char8 as BS
+
+import Initialize (buildFromSource)
+import Generate.JavaScript
+import Generate.Noscript
+
+data JSStyle = Minified | Readable
+data JSSource = Link String | Source JSStyle String
+
+makeScript :: JSSource -> H.Html
+makeScript source =
+    case source of
+      Link src -> H.script ! A.type_ "text/javascript" ! A.src (H.toValue src) $ ""
+      Source style src ->
+          H.script ! A.type_ "text/javascript" $
+           preEscapedToMarkup $ case style of 
+                                  Minified -> BS.unpack . minify . BS.pack $ src
+                                  Readable -> src
+
+-- |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-runtime.js as expected by the browser
+             -> String -- ^ The page title
+             -> String -- ^ The elm source code.
+             -> H.Html
+generateHtml libLoc title source = error "function 'generateHtml' is unimplemented for now"
+
+createHtml :: FilePath -> String -> [JSSource] -> String -> String -> H.Html
+createHtml libLoc title scripts moduleName noscript =
+    H.docTypeHtml $ do 
+      H.head $ do
+        H.meta ! A.charset "UTF-8"
+        H.title . H.toHtml $ title
+        makeScript (Link libLoc)
+        mapM_ makeScript scripts
+      H.body $ do
+        H.script ! A.type_ "text/javascript" $
+               preEscapedToMarkup ("Elm.fullscreen(Elm." ++ moduleName ++ ")")
+        H.noscript $ preEscapedToMarkup noscript
diff --git a/compiler/Generate/JavaScript.hs b/compiler/Generate/JavaScript.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Generate/JavaScript.hs
@@ -0,0 +1,365 @@
+module Generate.JavaScript (jsModule) where
+
+import Control.Arrow (first,second)
+import Control.Monad (liftM,(<=<),join,ap)
+import Data.Char (isAlpha,isDigit)
+import qualified Data.List as List
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import Data.Either (partitionEithers)
+import qualified Text.Pandoc as Pan
+
+import Unique
+import Generate.Cases
+import SourceSyntax.Everything
+import SourceSyntax.Location
+import qualified Transform.SortDefinitions as SD
+
+deprime :: String -> String
+deprime = map (\c -> if c == '\'' then '$' else c)
+
+indent = concatMap f
+    where f '\n' = "\n  "
+          f c = [c]
+
+internalImports name =
+    [ ("N" , "Elm.Native"),
+      ("_N", "N.Utils(elm)"),
+      ("_L", "N.List(elm)"),
+      ("_E", "N.Error(elm)"),
+      ("_J", "N.JavaScript(elm)"),
+      ("_str", "_J.toString"),
+      ("$moduleName", quoted name)
+    ]
+
+parens s  = "(" ++ s ++ ")"
+brackets s  = "{" ++ s ++ "}"
+commaSep = List.intercalate ", "
+dotSep = List.intercalate "."
+jsObj = brackets . commaSep
+jsList ss = "["++ List.intercalate "," ss ++"]"
+jsFunc args body = "function(" ++ args ++ "){" ++ indent body ++ "}"
+assign x e = "\nvar " ++ x ++ " = " ++ e ++ ";"
+ret e = "\nreturn "++ e ++";"
+quoted s  = "'" ++ concatMap f s ++ "'"
+    where f '\n' = "\\n"
+          f '\'' = "\\'"
+          f '\t' = "\\t"
+          f '\"' = "\\\""
+          f '\\' = "\\\\"
+          f c    = [c]
+
+globalAssign n e = "\n" ++ assign' n e ++ ";"
+assign' n e = n ++ " = " ++ e
+
+jsModule :: MetadataModule t v -> String
+jsModule modul =
+    run $ do
+      body <- toJS . fst . SD.flattenLets [] $ program modul
+      foreignImport <- mapM importEvent (foreignImports modul)
+      return $ concat [ setup ("Elm": names modul)
+                      , globalAssign ("Elm." ++ modName)
+                                     (jsFunc "elm" $ makeProgram body foreignImport) ]
+  where
+    modName  = dotSep (names modul)
+    makeProgram body foreignImport =
+        concat [ "\nvar " ++ usefulFuncs ++ ";"
+               , concatMap jsImport (imports modul)
+               , concat foreignImport
+               , assign "_op" "{}"
+               , body
+               , concatMap exportEvent $ foreignExports modul
+               , jsExports
+               ]
+    setup names = concatMap (\n -> globalAssign n $ n ++ " || {}") .
+                  map dotSep . drop 2 . List.inits $ init names
+    usefulFuncs = commaSep (map (uncurry assign') (internalImports modName))
+
+    jsExports = setup ("elm" : names modul) ++
+                ret (assign' ("elm." ++ modName) (brackets exs))
+        where
+          exs = indent . commaSep . concatMap (pair . deprime) $ "_op" : exports modul
+          pair x | isOp x = []
+                 | otherwise = ["\n" ++ x ++ " : " ++ x]
+
+
+    importEvent (js,base,elm,_) =
+        do v <- toJS' base
+           return $ concat [ "\nvar " ++ elm ++ "=Signal.constant(" ++ v ++ ");"
+                           , "\ndocument.addEventListener('", js
+                           , "_' + elm.id, function(e) { elm.notify(", elm
+                           , ".id, e.value); });" ]
+
+    exportEvent (js,elm,_) =
+        concat [ "\nA2( Signal.lift, function(v) { "
+               , "var e = document.createEvent('Event');"
+               , "e.initEvent('", js, "_' + elm.id, true, true);"
+               , "e.value = v;"
+               , "document.dispatchEvent(e); return v; }, ", elm, ");" ]
+
+jsImport (modul, method) =
+    concat $ zipWith3 (\s n v -> s ++ assign' n v ++ ";") starters subnames values
+  where
+    starters = "\nvar " : repeat "\n"
+    values = map (\name -> name ++ " || {}") (init subnames) ++
+             ["Elm." ++ modul ++ parens "elm"]
+    subnames = map dotSep . tail . List.inits $ split modul
+
+    split names = case go [] names of
+                    (name, []) -> [name]
+                    (name, ns) -> name : split ns
+    go name str = case str of
+                    '.':rest -> (reverse name, rest)
+                    c:rest   -> go (c:name) rest
+                    []       -> (reverse name, [])
+
+
+class ToJS a where
+  toJS :: a -> Unique String
+
+
+instance ToJS (Def t v) where
+
+  -- TODO: Make this handle patterns besides plain variables
+  toJS (Def (PVar x) e)
+      | isOp x = globalAssign ("_op['" ++ x ++ "']")  `liftM` toJS' e
+      | otherwise = assign (deprime x) `liftM` toJS' e
+
+  toJS (Def pattern e@(L s _)) =
+      do n <- guid
+         let x = "_" ++ show n
+             var = L s . Var
+             toDef y' = let y = deprime y' in
+                        Def (PVar y) (L s $ Case (var x) [(pattern, var y)])
+         stmt <- assign x `liftM` toJS' e
+         vars <- toJS . map toDef . Set.toList $ SD.boundVars pattern
+         return (stmt ++ vars)
+
+  toJS (TypeAnnotation _ _) = return ""
+
+
+instance ToJS a => ToJS [a] where
+  toJS xs = concat `liftM` mapM toJS xs
+
+toJS' :: LExpr t v -> Unique String
+toJS' (L span expr) =
+    case expr of
+      MultiIf ps -> multiIfToJS span ps
+      Case e cases -> caseToJS span e cases
+      _ -> toJS expr
+
+remove x e = "_N.remove('" ++ deprime x ++ "', " ++ e ++ ")"
+addField x v e = "_N.insert('" ++ deprime x ++ "', " ++ v ++ ", " ++ e ++ ")"
+setField fs e = "_N.replace(" ++ jsList (map f fs) ++ ", " ++ e ++ ")"
+    where f (x,v) = "['" ++ deprime x ++ "'," ++ v ++ "]"
+access x e = e ++ "." ++ deprime x
+makeRecord kvs = record `liftM` collect kvs
+  where
+    combine r (k,v) = Map.insertWith (++) k v r
+    collect = liftM (List.foldl' combine Map.empty) . mapM prep
+    prep (k, e) =
+        do v <- toJS' e
+           return (deprime k, [v])
+    fields fs =
+        brackets ("\n  "++List.intercalate ",\n  " (map (\(k,v) -> k++":"++v) fs))
+    hidden = fields . map (second jsList) .
+             filter (not . null . snd) . Map.toList . Map.map tail
+    record kvs = fields . (("_", hidden kvs) :) . Map.toList . Map.map head $ kvs
+
+
+instance ToJS Literal where
+ toJS lit =
+  case lit of
+    Chr c -> return $ quoted [c]
+    Str s -> return $ "_str" ++ parens (quoted s)
+    IntNum   n -> return $ show n
+    FloatNum n -> return $ show n
+    Boolean  b -> return $ if b then "true" else "false"
+
+
+instance ToJS (Expr t v) where
+ toJS expr =
+  case expr of
+    Var x -> return (deprime x)
+    Literal lit -> toJS lit
+    Range lo hi -> jsRange `liftM` toJS' lo `ap` toJS' hi
+    Access e x -> access x `liftM` toJS' e
+    Remove e x -> remove x `liftM` toJS' e
+    Insert e x v -> addField x `liftM` toJS' v `ap` toJS' e
+    Modify e fs -> do fs' <- (mapM (\(x,v) -> (,) x `liftM` toJS' v) fs)
+                      setField fs' `liftM` toJS' e
+    Record fs -> makeRecord fs
+    Binop op e1 e2 -> binop op e1 e2
+
+    Lambda p e@(L s _) -> liftM fastFunc (toJS' body)
+        where
+          fastFunc body
+              | length args < 2 || length args > 9 =
+                  foldr (\arg bod -> jsFunc arg (ret bod)) body args
+              | otherwise =
+                  "F" ++ show (length args) ++ parens (jsFunc (commaSep args) (ret body))
+
+          (args, body) = first reverse $ foldr depattern ([], innerBody) (zip patterns [1..])
+
+          depattern (pattern,n) (args, body) =
+            case pattern of
+              PVar x -> (deprime x : args, body)
+              _ -> let arg = "arg" ++ show n
+                   in  (arg:args, L s (Case (L s (Var arg)) [(pattern, body)]))
+
+          (patterns, innerBody) = collect [p] e
+
+          collect patterns lexpr@(L _ expr) =
+            case expr of
+              Lambda p e -> collect (p:patterns) e
+              _ -> (patterns, lexpr)
+
+    App e1 e2 -> jsApp e1 e2
+    Let defs e -> jsLet $ SD.flattenLets defs e 
+
+    ExplicitList es ->
+        do es' <- mapM toJS' es
+           return $ "_J.toList" ++ parens (jsList es')
+
+    Data name es ->
+        do fs <- mapM toJS' es
+           return $ case name of
+              "[]" -> jsNil
+              "::" -> jsCons (head fs) ((head . tail) fs)
+              _ -> jsObj $ ("ctor:" ++ show name) : fields
+                   where fields = zipWith (\n e -> "_" ++ show n ++ ":" ++ e) [0..] fs
+
+    Markdown doc -> return $ "Text.text('" ++ pad ++ md ++ pad ++ "')"
+        where pad = "<div style=\"height:0;width:0;\">&nbsp;</div>"
+              md = formatMarkdown $ Pan.writeHtmlString Pan.def doc
+
+jsApp e1 e2 =
+    do f  <- toJS' func
+       as <- mapM toJS' args
+       return $ case as of
+                  [a] -> f ++ parens a
+                  _   -> "A" ++ show (length as) ++ parens (commaSep (f:as))
+  where
+    (func, args) = go [e2] e1
+    go args e =
+       case e of
+         (L _ (App e1 e2)) -> go (e2 : args) e1
+         _ -> (e, args)
+
+formatMarkdown = concatMap f
+    where f '\'' = "\\'"
+          f '\n' = "\\n"
+          f '"'  = "\""
+          f c = [c]
+
+multiIfToJS span ps =
+    case last ps of
+      (L _ (Var "otherwise"), e) -> toJS' e >>= \b -> format b (init ps)
+      _ -> format ("_E.If" ++ parens ("$moduleName," ++ quoted (show span))) ps
+  where
+    format base ps =
+        foldr (\c e -> parens $ c ++ " : " ++ e) base `liftM` mapM f ps
+    f (b,e) = do b' <- toJS' b
+                 e' <- toJS' e
+                 return (b' ++ " ? " ++ e')
+
+jsLet (defs,e') = do ds <- mapM toJS defs
+                     e <- toJS' e'
+                     return $ jsFunc "" (concat ds ++ ret e) ++ "()"
+
+caseToJS span e ps = do
+  (tempVar,match) <- caseToMatch ps
+  e' <- toJS' e
+  let (match',stmt) = case e of
+        L _ (Var x) -> (matchSubst [(tempVar,deprime x)] match, "")
+        _           -> (match, assign tempVar e')
+  matches <- matchToJS span match'
+  return $ jsFunc "" (stmt ++ matches) ++ "()"
+
+matchToJS span match =
+  case match of
+    Match name clauses def ->
+        do cases <- concat `liftM` mapM (clauseToJS span name) clauses
+           finally <- matchToJS span def
+           let isLiteral p = case p of
+                               Clause (Right _) _ _ -> True
+                               _ -> False
+               access = if any isLiteral clauses then "" else ".ctor"
+           return $ concat [ "\nswitch (", name, access, ") {"
+                           , indent cases, "\n}", finally ]
+    Fail -> return ("_E.Case" ++ parens ("$moduleName," ++ quoted (show span)))
+    Break -> return "break;"
+    Other e -> ret `liftM` toJS' e
+    Seq ms -> concat `liftM` mapM (matchToJS span) (dropEnd [] ms)
+        where
+          dropEnd acc [] = acc
+          dropEnd acc (m:ms) =
+              case m of
+                Other _ -> acc ++ [m]
+                _ -> dropEnd (acc ++ [m]) ms
+
+clauseToJS span var (Clause value vars e) = do
+  let vars' = map (\n -> var ++ "._" ++ show n) [0..]
+  s <- matchToJS span $ matchSubst (zip vars vars') e
+  return $ concat [ "\ncase ", case value of
+                                 Right (Boolean True)  -> "true"
+                                 Right (Boolean False) -> "false"
+                                 Right lit -> show lit
+                                 Left name -> quoted $ case List.elemIndices '.' name of
+                                                         [] -> name
+                                                         is -> drop (last is + 1) name
+                  , ":", indent s ]
+
+jsNil         = "_L.Nil"
+jsCons  e1 e2 = "_L.Cons(" ++ e1 ++ "," ++ e2 ++ ")"
+jsRange e1 e2 = "_L.range" ++ parens (e1 ++ "," ++ e2)
+jsCompare e1 e2 op = parens ("_N.cmp(" ++ e1 ++ "," ++ e2 ++ ")" ++ op)
+
+
+binop op e1 e2
+    | op == "Basics.." =
+        do ss <- mapM toJS' (e1 : collect [] e2)
+           return . jsFunc "$" . ret $ apply "$" ss
+    | op == "Basics.<|" =
+        do arg <- toJS' e2
+           funcs <- mapM toJS' (collect [] e1)
+           return (apply arg funcs)
+    | otherwise =
+        binopNormal op `liftM` toJS' e1 `ap` toJS' e2
+  where
+    apply = foldr (\f arg-> f ++ parens arg)
+
+    collect es e =
+        case e of
+          L _ (Binop op e1 e2) | op == "Basics.." -> collect (es ++ [e1]) e2
+          _ -> es ++ [e]
+
+binopNormal op s1 s2 =
+  case Map.lookup op opDict of
+    Just e -> e
+    Nothing -> "A2" ++ parens (commaSep [ prefix ++ func, s1, s2 ])
+  where
+    func | isOp op'  = "_op['" ++ op' ++ "']"
+         | otherwise = op'
+    (prefix, op') = case List.elemIndices '.' op of
+                      [] -> ("", op)
+                      xs -> splitAt (last xs + 1) op
+
+    opDict = Map.fromList $ basics ++
+             [ ("::", jsCons s1 s2)
+             , ("List.++", "_L.append" ++ parens (s1 ++ "," ++ s2)) ]
+
+    ops = pow : map (\op -> (op, parens (s1 ++ op ++ s2))) ["+","-","*","/","&&","||"]
+        where pow = ("^" , "Math.pow(" ++ s1 ++ "," ++ s2 ++ ")")
+
+    basics = ops ++ map (\(op,e) -> ("Basics." ++ op, e))
+             (ops ++ [ ("<|", s1 ++ parens s2)
+                     , ("|>", s2 ++ parens s1)
+                     , ("==", "_N.eq(" ++ s1 ++ "," ++ s2 ++ ")")
+                     , ("/=", "!_N.eq(" ++ s1 ++ "," ++ s2 ++ ")")
+                     , ("<" , jsCompare s1 s2 "<0")
+                     , (">" , jsCompare s1 s2 ">0")
+                     , ("<=", jsCompare s1 s2 "<1")
+                     , (">=", jsCompare s1 s2 ">-1")
+                     , ("div", parens (s1 ++ "/" ++ s2 ++ "|0"))
+                     ])
diff --git a/compiler/Generate/Noscript.hs b/compiler/Generate/Noscript.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Generate/Noscript.hs
@@ -0,0 +1,65 @@
+module Generate.Noscript (noscript) where
+
+import Data.List (isInfixOf)
+import SourceSyntax.Everything
+import qualified Text.Pandoc as Pan
+
+noscript :: Module t v -> String
+noscript modul = concat (extract modul)
+
+class Extract a where
+  extract :: a -> [String]
+
+instance Extract (Module t v) where
+  extract (Module _ _ _ stmts) =
+      map (\s -> "<p>" ++ s ++ "</p>") (concatMap extract stmts)
+
+instance Extract (Declaration t v) where
+  extract (Definition d) = extract d
+  extract _ = []
+
+instance Extract (Def t v) where
+  extract (Def _ e)   = extract e
+  extract _ = []
+
+instance Extract e => Extract (Located e) where
+  extract (L _ e) = extract e
+
+instance Extract (Expr t v) where
+  extract expr =
+    let f = extract in
+    case expr of
+      Literal (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 (L _ (App (L _ (App (L _ (Var func)) w)) h)) src
+          | "image" `isInfixOf` func -> extractImage src
+      App (L _ (App (L _ (Var func)) src)) txt
+          | "link" `isInfixOf` func -> extractLink src txt
+      App (L _ (Var func)) e
+          | "header"    `isInfixOf` func -> tag "h1" e
+          | "bold"      `isInfixOf` func -> tag "b" e
+          | "italic"    `isInfixOf` func -> tag "i" e
+          | "monospace" `isInfixOf` func -> tag "code" e
+      App e1 e2 -> f e1 ++ f e2
+      Let defs e -> concatMap extract defs ++ f e
+      Var _ -> []
+      Case e cases -> concatMap (f . snd) cases
+      Data _ es -> concatMap f es
+      MultiIf es -> concatMap (f . snd) es
+      Markdown doc -> [ Pan.writeHtmlString Pan.def doc ]
+      _ -> []
+
+extractLink src txt =
+    case (extract src, extract txt) of
+      ([s1],[s2]) -> [ "<a href=\"" ++ s1 ++ "\">" ++ s2 ++ "</a>" ]
+      ( ss1, ss2) -> ss1 ++ ss2
+
+extractImage src =
+    case extract src of
+      [s] -> ["<img src=\"" ++ s ++ "\">"]
+      ss  -> ss
+
+tag t e = map (\s -> concat [ "<", t, ">", s, "</", t, ">" ]) (extract e)
diff --git a/compiler/Initialize.hs b/compiler/Initialize.hs
--- a/compiler/Initialize.hs
+++ b/compiler/Initialize.hs
@@ -1,96 +1,105 @@
-module Initialize (build, buildFromSource) where
+module Initialize (buildFromSource, getSortedDependencies) where
 
-import Control.Applicative ((<$>))
-import Control.Monad.Error
-import Data.List (lookup,nub)
+import Data.Data
+import Control.Monad.State
+import qualified Data.Graph as Graph
+import qualified Data.List as List
 import qualified Data.Map as Map
+import qualified Data.Set as Set
+import System.Exit
+import System.FilePath as FP
+import Text.PrettyPrint (Doc)
 
-import Ast
-import Data.Either (lefts,rights)
-import Data.List (intercalate,partition)
-import Parse.Parser (parseProgram, preParse)
-import Rename
-import qualified Libraries as Libs
-import Types.Types ((-:))
-import Types.Hints (hints)
-import Types.Unify
-import Types.Alias (dealias, mistakes)
-import Optimize
-import CompileToJS (jsModule)
+import SourceSyntax.Everything
+import SourceSyntax.Type
+import qualified Parse.Parse as Parse
+import qualified Metadata.Prelude as Prelude
+import qualified Transform.Check as Check
+import qualified Transform.SortDefinitions as SD
+import qualified Type.Inference as TI
+import qualified Type.Constrain.Declaration as TcDecl
+import qualified Transform.Canonicalize as Canonical
 
-checkMistakes :: Module -> Either String Module
-checkMistakes modul@(Module name ex im stmts) = 
-  case mistakes stmts of
-    m:ms -> Left (unlines (m:ms))
-    []   -> return modul
+buildFromSource :: Bool -> Interfaces -> String -> Either [Doc] (MetadataModule () ())
+buildFromSource noPrelude interfaces source =
+  do let add = if noPrelude then id else Prelude.add
+     modul@(Module _ _ _ decls') <- add `fmap` Parse.program source
 
-checkTypes :: Module -> Either String Module
-checkTypes modul =
-  do subs <- unify hints modul
-     subs `seq` return (optimize (renameModule modul))
+     -- check for structural errors
+     Module names exs ims decls <-
+         case Check.mistakes decls' of
+           [] -> return modul
+           ms -> Left ms
 
-check :: Module -> Either String Module
-check = checkMistakes >=> checkTypes
+     let exports'
+             | null exs =
+                 let get = Set.toList . SD.boundVars in
+                 concat [ get pattern | Definition (Def pattern _) <- decls ] ++
+                 concat [ map fst ctors | Datatype _ _ ctors <- decls ]
+             | otherwise = exs
 
-buildFromSource :: Bool -> String -> Either String Module
-buildFromSource withPrelude src = (check . add) =<< (parseProgram src)
-    where add = if withPrelude then Libs.addPrelude else id
+     metaModule <- Canonical.metadataModule interfaces $ MetadataModule {
+           names = names,
+           path = FP.joinPath names,
+           exports = exports',
+           imports = ims,
+           -- reorder AST into strongly connected components
+           program = SD.sortDefs . dummyLet $ TcDecl.toExpr decls,
+           types = Map.empty,
+           datatypes = [ (name,vars,ctors) | Datatype name vars ctors <- decls ],
+           fixities = [ (assoc,level,op) | Fixity assoc level op <- decls ],
+           aliases = [ (name,tvs,tipe) | TypeAlias name tvs tipe <- decls ],
+           foreignImports = [ (evt,v,name,typ) | ImportEvent evt v name typ <- decls ],
+           foreignExports = [ (evt,name,typ) | ExportEvent evt name typ <- decls ]
+          }
 
-build :: Bool -> FilePath -> IO (Either String [Module])
-build withPrelude root = do
-  names <- getSortedModuleNames root
-  case names of
-    Left err -> return (Left err)
-    Right ns -> do srcs <- zipWithM buildFile' [1..] ns
-                   return (sequence srcs)
-      where
-        buildFile' n name = putStrLn (msg n name) >> buildFile withPrelude name
-        msg n name = "["++show n++" of "++show (length ns)++"] Compiling "++name
+     types <- TI.infer interfaces metaModule
 
-buildFile :: Bool -> String -> IO (Either String Module)
-buildFile withPrelude moduleName =
-  let filePath = toFilePath moduleName in
-  case isNative moduleName of
-    True  -> return (Right $ Module [moduleName] [] [] [])
-             --return (Left "Can't do that yet")
-             --Right `liftM` readFile filePath
-    False -> do txt <- readFile filePath
-                return $ buildFromSource withPrelude txt
+     return $ metaModule { types = types }
 
 
-getSortedModuleNames :: FilePath -> IO (Either String [String])
-getSortedModuleNames root = do
-  deps <- readDeps [] root
-  return (sortDeps =<< deps)
+getSortedDependencies :: Bool -> FilePath -> IO [String]
+getSortedDependencies noPrelude root =
+    sortDeps =<< readDeps noPrelude root
 
-type Deps = (String, [String])
+type Deps = (FilePath, String, [String])
 
-sortDeps :: [Deps] -> Either String [String]
-sortDeps deps = go [] (nub deps)
-    where
-      msg = "A cyclical or missing module dependency or was detected in: "
+sortDeps :: [Deps] -> IO [String]
+sortDeps depends =
+    if null mistakes
+    then return (concat sccs)
+    else print msg >> mapM print mistakes >> exitFailure
+  where
+    sccs = map Graph.flattenSCC $ Graph.stronglyConnComp depends
 
-      go :: [String] -> [Deps] -> Either String [String]
-      go sorted [] = Right sorted
-      go sorted unsorted =
-          case partition (all (`elem` sorted) . snd) unsorted of
-            ([],m:ms) -> Left (msg ++ intercalate ", " (map fst (m:ms)) ++ show sorted ++ show unsorted)
-            (srtd,unsrtd) -> go (sorted ++ map fst srtd) unsrtd
+    mistakes = filter (\scc -> length scc > 1) sccs
+    msg = "A cyclical module dependency or was detected in: "
 
-readDeps :: [FilePath] -> FilePath -> IO (Either String [Deps])
-readDeps seen root = do
-  txt <- readFile root
-  case preParse txt of
-    Left err -> return (Left err)
-    Right (name,deps) -> do rest <- mapM (readDeps seen' . toFilePath) newDeps
-                            return $ do rs <- sequence rest
-                                        return ((name, realDeps) : concat rs)
-        where realDeps = filter (`notElem` builtIns) deps
-              newDeps = filter (`notElem` seen) realDeps
-              seen' = root : seen ++ newDeps
-              builtIns = Map.keys Libs.libraries
+readDeps :: Bool -> FilePath -> IO [Deps]
+readDeps noPrelude root = evalStateT (go root) Set.empty
+  where
+    builtIns = if noPrelude then Set.empty
+                            else Set.fromList (Map.keys Prelude.interfaces)
 
-isNative name = takeWhile (/='.') name == "Native"
+    go :: FilePath -> StateT (Set.Set String) IO [Deps]
+    go root = do
+      txt <- liftIO $ readFile root
+      case Parse.dependencies txt of
+        Left err -> liftIO (putStrLn msg >> print err >> exitFailure)
+            where msg = "Error resolving dependencies in " ++ root ++ ":"
+                    
+        Right (name,deps) ->
+            do seen <- get
+               let realDeps = Set.difference (Set.fromList deps) builtIns
+                   newDeps = Set.difference (Set.filter (not . isNative) realDeps) seen
+               put (Set.insert name (Set.union newDeps seen))
+               rest <- mapM (go . toFilePath) (Set.toList newDeps)
+               return ((makeRelative "." root, name, Set.toList realDeps) : concat rest)
+                       
+
+isNative name = List.isPrefixOf "Native." name
+
+toFilePath :: String -> FilePath
 toFilePath name = map swapDots name ++ ext
     where swapDots '.' = '/'
           swapDots  c  =  c
diff --git a/compiler/Language/Elm.hs b/compiler/Language/Elm.hs
--- a/compiler/Language/Elm.hs
+++ b/compiler/Language/Elm.hs
@@ -1,45 +1,36 @@
-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
 {- | This module exports the functions necessary for compiling Elm code into the
-     respective HTML, JS and CSS code.
-
-     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.
+     respective HTML, CSS, and JS code.
 
      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 (
-    compile, toHtml,
-    moduleName,
-    runtime, docs
-    ) where
+module Language.Elm (compile, moduleName, runtime) where
 
-import qualified Ast as Ast
-import qualified Libraries as Libraries
-import Data.List (intercalate)
+import qualified Data.List as List
+import qualified Data.Map as Map
 import Data.Version (showVersion)
-import CompileToJS (showErr, jsModule)
-import ExtractNoscript
-import GenerateHtml
-import Initialize
+import Generate.JavaScript (jsModule)
+import Generate.Html (generateHtml)
+import Initialize (buildFromSource)
+import Parse.Module (getModuleName)
+import SourceSyntax.Module
 import Text.Blaze.Html (Html)
+import qualified Text.PrettyPrint as P
+import qualified Metadata.Prelude as Prelude
 import Paths_Elm
 
--- |This function compiles Elm code to JavaScript.
-compile :: String -> String
-compile source = either showErr jsModule modul
-  where modul = buildFromSource True source
+-- |This function compiles Elm code to JavaScript. It will return either
+--  an error message or the compiled JS code.
+compile :: String -> Either String String
+compile source =
+    case buildFromSource False Prelude.interfaces source of
+      Left docs -> Left . unlines . List.intersperse "" $ map P.render docs
+      Right modul -> Right $ jsModule (modul :: MetadataModule () ())
 
 -- |This function extracts the module name of a given source program.
-moduleName :: String -> String
-moduleName source = either (const "Main") getName modul
-  where modul = buildFromSource False source
-        getName (Ast.Module names _ _ _) = intercalate "." names
+moduleName :: String -> Maybe String
+moduleName = getModuleName
 
 -- |This function compiles Elm code into a full HTML page.
 toHtml :: String -- ^ Location of elm-min.js as expected by the browser
@@ -55,4 +46,3 @@
 -- |The absolute path to Elm's core library documentation.
 docs :: IO FilePath
 docs = getDataFileName "docs.json"
-
diff --git a/compiler/Language/Elm/Quasi.hs b/compiler/Language/Elm/Quasi.hs
deleted file mode 100644
--- a/compiler/Language/Elm/Quasi.hs
+++ /dev/null
@@ -1,93 +0,0 @@
-{-# 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/compiler/Metadata/Prelude.hs b/compiler/Metadata/Prelude.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Metadata/Prelude.hs
@@ -0,0 +1,59 @@
+module Metadata.Prelude (interfaces, add) where
+
+import qualified Data.Map as Map
+import qualified Control.Exception as E
+import qualified Paths_Elm as Path
+import System.Directory
+import System.Exit
+import System.FilePath
+import System.IO
+import System.IO.Unsafe (unsafePerformIO)
+import SourceSyntax.Module
+import qualified Data.Binary as Binary
+import qualified Data.ByteString.Lazy as BS
+
+
+add :: Module t v -> Module t v
+add (Module name exs ims stmts) = Module name exs (customIms ++ ims) stmts
+    where
+      customIms = concatMap addModule prelude
+
+      addModule (n, method) = case lookup n ims of
+                                Nothing     -> [(n, method)]
+                                Just (As m) -> [(n, method)]
+                                Just _      -> []
+
+prelude :: [(String, ImportMethod)]
+prelude = text ++ map (\n -> (n, Hiding [])) modules
+  where
+    text = map ((,) "Text") [ As "Text", Hiding ["link", "color", "height"] ]
+    modules = [ "Basics", "Signal", "List", "Maybe", "Time", "Prelude"
+              , "Graphics.Element", "Color", "Graphics.Collage" ]
+
+{-# NOINLINE interfaces #-}
+interfaces :: Interfaces
+interfaces =
+    unsafePerformIO (safeReadDocs =<< Path.getDataFileName "interfaces.data")
+
+safeReadDocs :: FilePath -> IO Interfaces
+safeReadDocs name =
+    E.catch (readDocs name) $ \err -> do
+      let _ = err :: IOError
+      putStrLn $ unlines [ "Error reading types for standard library!"
+                         , "    The file should be at " ++ name
+                         , "    If you are using a stable version of Elm,"
+                         , "    please report an issue at github.com/evancz/Elm"
+                         , "    and specify your versions of Elm and your OS" ]
+      exitFailure
+
+readDocs :: FilePath -> IO Interfaces
+readDocs name = do
+  exists <- doesFileExist name
+  case exists of
+    False -> ioError . userError $ "File Not Found"
+    True -> do
+      handle <- openBinaryFile name ReadMode
+      bits <- BS.hGetContents handle
+      let ifaces = Map.fromList (Binary.decode bits)
+      BS.length bits `seq` hClose handle
+      return ifaces
diff --git a/compiler/Model/Ast.hs b/compiler/Model/Ast.hs
deleted file mode 100644
--- a/compiler/Model/Ast.hs
+++ /dev/null
@@ -1,153 +0,0 @@
-
-module Ast where
-
-import Context
-import Data.Char (isDigit, isSymbol)
-import Data.List (intercalate)
-import Types.Types
-import qualified Text.Pandoc as Pandoc
-
-data Module = Module [String] Exports Imports [Statement]
-
-type Exports = [String]
-
-type Imports = [(String, ImportMethod)]
-data ImportMethod = As String | Importing [String] | Hiding [String]
-                    deriving (Eq, Ord, Show)
-
-
-data Pattern = PData String [Pattern]
-             | PRecord [String]
-             | PVar String
-             | PAnything
-               deriving (Eq)
-
-type CExpr = Context Expr
-data Expr = IntNum Int
-          | FloatNum Float
-          | Chr Char
-          | Str String
-          | Boolean Bool
-          | Range CExpr CExpr
-          | Access CExpr String
-          | Remove CExpr String
-          | Insert CExpr String CExpr
-          | Modify CExpr [(String,CExpr)]
-          | Record [(String,[String],CExpr)]
-          | Binop String CExpr CExpr
-          | Lambda String CExpr
-          | App CExpr CExpr
-          | If CExpr CExpr CExpr
-          | MultiIf [(CExpr,CExpr)]
-          | Let [Def] CExpr
-          | Var String
-          | Case CExpr [(Pattern,CExpr)]
-          | Data String [CExpr]
-          | Markdown Pandoc.Pandoc
-            deriving (Eq)
-
-data Def = FnDef String [String] CExpr
-         | OpDef String String String CExpr
-           deriving (Eq)
-
-data Statement = Definition Def
-               | Datatype String [X] [(String,[Type])]
-               | TypeAlias String [X] Type
-               | TypeAnnotation String Type
-               | ImportEvent String CExpr String Type
-               | ExportEvent String String Type
-                 deriving (Eq,Show)
-
-cons h t = epos h t (Data "Cons" [h,t])
-nil      = C (Just "[]") NoSpan (Data "Nil" [])
-list     = foldr cons nil
-tuple es = Data ("Tuple" ++ show (length es)) es
-
-delist (C _ _ (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
-
-brkt s = "{ " ++ s ++ " }"
-parensIf b s = if b then parens s else s
-isOp c = isSymbol c || elem c "+-/*=.$<>:&|^?%#@~!"
-
-instance Show Pattern where
-  show p =
-   case p of
-     PRecord fs -> brkt (intercalate ", " fs)
-     PVar x -> x
-     PAnything -> "_"
-     PData "Cons" [hd@(PData "Cons" _),tl] ->
-        parens (show hd) ++ " :: " ++ show tl
-     PData "Cons" [hd,tl] -> show hd ++ " : " ++ show tl
-     PData "Nil" [] -> "[]"
-     PData name ps ->
-        if take 5 name == "Tuple" && all isDigit (drop 5 name) then
-            parens . intercalate ", " $ map show ps
-        else parensIf (not (null ps)) $ unwords (name : map show ps)
-
-instance Show Expr where
-  show e =
-   let show' (C _ _ e) = parensIf (needsParens e) (show e) in
-   case e of
-     IntNum n -> show n
-     FloatNum n -> show n
-     Chr c -> show c
-     Str s -> show s
-     Boolean b -> show b
-     Range e1 e2 -> "[" ++ show e1 ++ ".." ++ show e2 ++ "]"
-     Access e x -> show' e ++ "." ++ x
-     Remove e x -> brkt (show e ++ " - " ++ x)
-     Insert (C _ _ (Remove e y)) x v ->
-         brkt (show e ++ " - " ++ y ++ " | " ++ x ++ " = " ++ show v)
-     Insert e x v -> brkt (show e ++ " | " ++ x ++ " = " ++ show v)
-     Modify e fs -> brkt (show e ++" | "++ intercalate ", " (map field fs))
-         where field (x,e) = x ++ " <- " ++ show e
-     Record r -> brkt (intercalate ", " (map fields r))
-         where fields (f,args,e) = f ++ concatMap (' ':) args ++ " = " ++ show e
-     Binop op e1 e2 -> show' e1 ++ " " ++ op ++ " " ++ show' e2
-     Lambda x e -> let (xs,e') = getLambdas (noContext $ Lambda x e) in
-                      concat [ "\\", intercalate " " xs, " -> ", show e' ]
-     App e1 e2 -> show' e1 ++ " " ++ show' e2
-     If e1 e2 e3 -> concat [ "if ", show e1, " then ", show e2, " else ", show e3 ]
-     MultiIf (p:ps) -> concat [ "if | ", iff p, sep (map iff ps) ]
-         where iff (b,e) = show b ++ " -> " ++ show e
-               sep = concatMap ("\n   | " ++)
-     Let defs e -> "let { "++intercalate " ; " (map show defs)++" } in "++show e
-     Var (c:cs) -> if isOp c then parens (c:cs) else c:cs
-     Case e pats -> "case "++ show e ++" of " ++ brkt (intercalate " ; " pats')
-         where pats' = map (\(p,e) -> show p ++ " -> " ++ show e) pats
-     Data name es
-          | name == "Cons" -> ("["++) . (++"]") . intercalate "," . map show $
-                              delist (noContext $ Data "Cons" es)
-          | name == "Nil"  -> "[]"
-          | otherwise      -> name ++ " " ++ intercalate " " (map show' es)
-     Markdown _ -> "[markdown| ... |]"
-
-
-instance Show Def where
-  show e =
-   case e of
-     FnDef v [] e     -> v ++ " = " ++ show e
-     FnDef f args e   -> f ++ " " ++ intercalate " " args ++ " = " ++ show e
-     OpDef op a1 a2 e -> intercalate " " [a1,op,a2] ++ " = " ++ show e
-
-getLambdas (C _ _ (Lambda x e)) = (x:xs,e')
-    where (xs,e') = getLambdas e
-getLambdas e = ([],e)
-
-needsParens e =
-  case e of
-    Binop _ _ _ -> True
-    Lambda _ _ -> True
-    App _ _ -> True
-    If _ _ _ -> True
-    Let _ _ -> True
-    Case _ _ -> True
-    Data name (x:xs) -> name /= "Cons"
-    _ -> False
diff --git a/compiler/Model/Context.hs b/compiler/Model/Context.hs
deleted file mode 100644
--- a/compiler/Model/Context.hs
+++ /dev/null
@@ -1,43 +0,0 @@
-
-module Context where
-
-import Text.Parsec.Pos
-
-
-data SrcPos = Pos Int Int
-    deriving (Eq,Ord)
-
-data SrcSpan = Span SrcPos SrcPos | NoSpan
-    deriving (Eq,Ord)
-
-data Context e = C (Maybe String) SrcSpan e deriving (Eq,Ord)
-
-
-instance Show SrcPos where
-    show (Pos r c) = "Line " ++ show r ++ ", Column " ++ show c
-
-instance Show SrcSpan where
-  show span = 
-      case span of
-        Span start end -> show start
-        NoSpan -> ""
-
-instance Show e => Show (Context e) where
-  show (C _ _ e) = show e
-
-
-
-noContext = C Nothing NoSpan
-
-pos start end = C Nothing
-                  (Span (Pos (sourceLine start) (sourceColumn start))
-                        (Pos (sourceLine end  ) (sourceColumn end  )))
-
-epos (C _ s1 _) (C _ s2 _) = C Nothing span
-    where span = case (s1,s2) of
-                   (Span start _, Span _ end) -> Span start end
-                   (_, NoSpan) -> s1
-                   (NoSpan, _) -> s2
-
-addCtx x (C Nothing span e) = C (Just (show x)) span e
-addCtx x (C txt span e) = C txt span e
diff --git a/compiler/Model/Guid.hs b/compiler/Model/Guid.hs
deleted file mode 100644
--- a/compiler/Model/Guid.hs
+++ /dev/null
@@ -1,19 +0,0 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-module Guid (guid, set, run, runAt, GuidCounter) where
-
-import Control.Monad.State (evalState, State, get, put)
-
--- Wrapper around State monad.
-newtype GuidCounter a = GC { runGC :: State Int a }
-    deriving (Monad)
-
--- Get the next GUID, incrementing the counter.
-guid :: GuidCounter Int
-guid = GC $ do n <- get
-               put (n + 1)
-               return n
-
-set n = GC (put n)
-
-run = runAt 0
-runAt n x = evalState (runGC x) n
diff --git a/compiler/Model/Libraries.hs b/compiler/Model/Libraries.hs
deleted file mode 100644
--- a/compiler/Model/Libraries.hs
+++ /dev/null
@@ -1,59 +0,0 @@
-module Libraries (libraries, addPrelude) where
-
-import Ast
-import Control.Applicative ((<$>),(<*>))
-import qualified Data.Map as Map
-import Data.List (inits)
-import Text.JSON
-import LoadLibraries as Libs
-
-addPrelude :: Module -> Module
-addPrelude (Module name exs ims stmts) = Module name exs (customIms ++ ims) stmts
-    where customIms = concatMap addModule prelude
-
-          addModule (n, method) = case lookup n ims of
-                                    Nothing     -> [(n, method)]
-                                    Just (As m) -> [(n, method)]
-                                    Just _      -> []
-
-prelude = text : map (\n -> (n, Hiding [])) modules
-  where
-    text = ("Text", Hiding ["link", "color", "height"])
-    modules = [ "Prelude", "Signal", "List", "Maybe", "Time"
-              , "Graphics.Element", "Color", "Graphics.Collage" ]
-
-libraries :: Map.Map String (Map.Map String String)
-libraries =
-    case getLibs of
-      Error err -> error err
-      Ok libs   -> Map.unionWith Map.union libs nilAndTuples
-          where nilAndTuples = Map.singleton "Prelude" (Map.fromList pairs)
-                pairs =
-                    [ ("Cons", "a -> [a] -> [a]")
-                    , ("Nil", "[a]")
-                    ] ++ map makeTuple (inits ['a'..'i'])
-                
-                makeTuple cs = 
-                    let name = "Tuple" ++ show (length cs)
-                    in  (name, concatMap (\c -> c : " -> ") cs ++
-                               name ++ concatMap (\c -> [' ',c]) cs)
-
-getLibs :: Result (Map.Map String (Map.Map String String))
-getLibs = do
-  obj <- decodeStrict Libs.docs :: Result (JSObject JSValue)
-  modules <- valFromObj "modules" obj :: Result [JSObject JSValue]
-  Map.fromList `fmap` mapM getValues modules
-
-
-get :: String -> JSObject JSValue -> Result String
-get = valFromObj
-
-getValue :: JSObject JSValue -> Result (String,String)
-getValue obj = (,) <$> get "name" obj <*> get "type" obj
-
-getValues :: JSObject JSValue -> Result (String, Map.Map String String)
-getValues obj = do
-  name <- get "name" obj
-  vs   <- valFromObj "values" obj
-  vals <- mapM getValue vs
-  return (name, Map.fromList vals)
diff --git a/compiler/Model/LoadLibraries.hs b/compiler/Model/LoadLibraries.hs
deleted file mode 100644
--- a/compiler/Model/LoadLibraries.hs
+++ /dev/null
@@ -1,34 +0,0 @@
-module LoadLibraries (docs) where
-
-import Control.DeepSeq (force)
-import qualified Control.Exception as E
-import Paths_Elm
-import System.Directory
-import System.FilePath
-import System.IO.Unsafe (unsafePerformIO)
-
--- See stackoverflow discussion for trade-off between using unsafeIO or TemplateHaskell:
--- http://stackoverflow.com/questions/12716215/load-pure-global-variable-from-file
-
--- Given the awkwardness of including a compile-time generated file
--- vs loading static data, then the unsafeIO seems better.
-
-{-# NOINLINE docs #-}
-docs :: String
-docs = force $ unsafePerformIO (safeReadDocs =<< getDataFileName "docs.json")
-
-safeReadDocs :: FilePath -> IO String
-safeReadDocs name = E.catch (readDocs name) (emitError name)
-
-readDocs :: FilePath -> IO String
-readDocs name = do
-  exists <- doesFileExist name
-  if exists then readFile name
-            else ioError . userError $ "File Not Found"
-
-
-emitError :: FilePath -> IOError -> IO String
-emitError name err = do
-    putStrLn $ "Error! Types for standard library not loaded properly!\n  File should be here:" ++ name ++ "\n  The file is created and copied by command: cabal install"
-    putStrLn (show err)
-    return "{\"modules\":[]}"
diff --git a/compiler/Parse/Binop.hs b/compiler/Parse/Binop.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Parse/Binop.hs
@@ -0,0 +1,111 @@
+module Parse.Binop (binops, infixStmt, OpTable) where
+
+import Control.Applicative ((<$>))
+import Control.Monad.Error
+import Data.List (intercalate)
+import qualified Data.Map as Map
+
+import SourceSyntax.Location (merge)
+import SourceSyntax.Expression (LExpr, Expr(Binop))
+import SourceSyntax.Declaration (Assoc(..))
+import Text.Parsec
+import Parse.Helpers
+
+type OpTable = [(Int, Assoc, String)]
+
+preludeTable :: OpTable
+preludeTable =
+  [ (9, R, ".")
+  , (8, R, "^")
+  , (7, L, "*"), (7, L, "/"), (7, L, "mod"), (7, L, "div"), (7, L, "rem")
+  , (6, L, "+"), (6, L, "-")
+  , (5, R, "::"), (5, R, "++")
+  , (4, N, "<="), (4, N, ">="), (4, N, "<")
+  , (4, N, "=="), (4, N, "/="), (4, N, ">")
+  , (4, L, "~"), (4, L, "<~")
+  , (3, R, "&&")
+  , (2, R, "||")
+  , (0, R, "<|"), (0, L, "|>")
+  ]
+
+opLevel :: OpTable -> String -> Int
+opLevel table op = Map.findWithDefault 9 op dict
+    where dict = Map.fromList (map (\(lvl,_,op) -> (op,lvl)) table)
+
+opAssoc :: OpTable -> String -> Assoc
+opAssoc table op = Map.findWithDefault R op dict
+    where dict = Map.fromList (map (\(_,assoc,op) -> (op,assoc)) table)
+
+hasLevel :: OpTable -> Int -> (String, LExpr t v) -> Bool
+hasLevel table n (op,_) = opLevel table op == n
+
+binops :: OpTable
+       -> IParser (LExpr t v)
+       -> IParser (LExpr t v)
+       -> IParser String
+       -> IParser (LExpr t v)
+binops table term last anyOp =
+    do e <- term
+       split (table ++ preludeTable) 0 e =<< nextOps
+    where
+      nextOps = choice [ commitIf (whitespace >> anyOp) $ do
+                           whitespace ; op <- anyOp ; whitespace
+                           expr <- Left <$> try term <|> Right <$> last
+                           case expr of
+                             Left t -> (:) (op,t) <$> nextOps
+                             Right e -> return [(op,e)]
+                       , return [] ]
+
+split :: OpTable
+      -> Int
+      -> LExpr t v
+      -> [(String, LExpr t v)]
+      -> IParser (LExpr t v)
+split _ _ e []  = return e
+split table n e eops = do
+  assoc <- getAssoc table n eops
+  es <- sequence (splitLevel table n e eops)
+  let ops = map fst (filter (hasLevel table n) eops)
+  case assoc of R -> joinR es ops
+                _ -> joinL es ops
+
+splitLevel :: OpTable -> Int -> LExpr t v -> [(String, LExpr t v)]
+           -> [IParser (LExpr t v)]
+splitLevel table n e eops =
+    case break (hasLevel table n) eops of
+      (lops, (op,e'):rops) ->
+          split table (n+1) e lops : splitLevel table n e' rops
+      (lops, []) -> [ split table (n+1) e lops ]
+
+joinL :: [LExpr t v] -> [String] -> IParser (LExpr t v)
+joinL [e] [] = return e
+joinL (a:b:es) (op:ops) = joinL (merge a b (Binop op a b) : es) ops
+joinL _ _ = fail "Ill-formed binary expression. Report a compiler bug."
+
+joinR :: [LExpr t v] -> [String] -> IParser (LExpr t v)
+joinR [e] [] = return e
+joinR (a:b:es) (op:ops) = do e <- joinR (b:es) ops
+                             return (merge a e (Binop op a e))
+joinR _ _ = fail "Ill-formed binary expression. Report a compiler bug."
+
+getAssoc :: OpTable -> Int -> [(String,LExpr t v)] -> IParser Assoc
+getAssoc table n eops
+    | all (==L) assocs = return L
+    | all (==R) assocs = return R 
+    | all (==N) assocs = case assocs of [_] -> return N
+                                        _   -> fail msg
+  where levelOps = filter (hasLevel table n) eops
+        assocs = map (opAssoc table . fst) levelOps
+        msg = concat [ "Conflicting precedence for binary operators ("
+                     , intercalate ", " (map fst eops), "). "
+                     , "Consider adding parentheses to disambiguate." ]
+
+infixStmt :: IParser (Int, Assoc, String)
+infixStmt =
+  let infx str assoc = try (reserved ("infix" ++ str) >> return assoc) in
+  do assoc <- choice [ infx "l" L, infx "r" R, infx "" N ]
+     whitespace
+     prec <- do n <- digit ; return (read [n] :: Int)
+     whitespace
+     op <- anyOp
+     return (prec, assoc, op)
diff --git a/compiler/Parse/Binops.hs b/compiler/Parse/Binops.hs
deleted file mode 100644
--- a/compiler/Parse/Binops.hs
+++ /dev/null
@@ -1,89 +0,0 @@
-module Parse.Binops (binops) where
-
-import Ast
-import Context
-import Control.Monad (liftM,guard)
-import Control.Monad.Error
-import Data.List (foldl',splitAt,elemIndices
-                 ,group,groupBy,sortBy,find,intercalate)
-import qualified Data.Map as Map
-import Data.Maybe (mapMaybe)
-
-import Text.Parsec
-import Parse.Library
-
-data Assoc = L | N | R deriving (Eq,Show)
-
-type OpTable = [(Int, Assoc, String)]
-
-table :: OpTable
-table = [ (9, R, ".")
-        , (8, R, "^")
-        , (7, L, "*"), (7, L, "/"), (7, L, "mod"), (7, L, "div"), (7, L, "rem")
-        , (6, L, "+"), (6, L, "-")
-        , (5, R, "::"), (5, R, "++")
-        , (4, N, "<="), (4, N, ">="), (4, N, "<")
-        , (4, N, "=="), (4, N, "/="), (4, N, ">")
-        , (4, L, "~"), (4, L, "<~")
-        , (3, R, "&&")
-        , (2, R, "||")
-        , (0, R, "$")
-        , (0, R, "<|"), (0, L, "|>")
-        ]
-
-opLevel op = Map.findWithDefault 9 op dict
-    where dict = Map.fromList (map (\(lvl,_,op) -> (op,lvl)) table)
-
-opAssoc op = Map.findWithDefault R op dict
-    where dict = Map.fromList (map (\(_,assoc,op) -> (op,assoc)) table)
-
-hasLevel n (op,e) = opLevel op == n
-
-sortOps :: OpTable -> OpTable
-sortOps = sortBy (\(i,_,_) (j,_,_) -> compare i j)
-
-binops :: IParser CExpr -> IParser String -> IParser CExpr
-binops term anyOp = do
-  e <- term
-  split 0 e =<< many (commitIf (whitespace >> anyOp) $ do
-                        whitespace ; op <- anyOp
-                        whitespace ; e <- term
-                        return (op,e))
-
-split :: Int -> CExpr -> [(String, CExpr)] -> IParser CExpr
-split _ e []  = return e
-split n e eops = do
-  assoc <- getAssoc n eops
-  es <- sequence (splitLevel n e eops)
-  let ops = map fst (filter (hasLevel n) eops)
-  case assoc of R -> joinR es ops
-                _ -> joinL es ops
-
-splitLevel :: Int -> CExpr -> [(String, CExpr)] -> [IParser CExpr]
-splitLevel n e eops =
-    case break (hasLevel n) eops of
-      (lops, (op,e'):rops) -> split (n+1) e lops : splitLevel n e' rops
-      (lops, []) -> [ split (n+1) e lops ]
-
-joinL :: [CExpr] -> [String] -> IParser CExpr
-joinL [e] [] = return e
-joinL (a:b:es) (op:ops) = joinL (epos a b (Binop op a b) : es) ops
-joinL _ _ = fail "Ill-formed binary expression. Report a compiler bug."
-
-joinR :: [CExpr] -> [String] -> IParser CExpr
-joinR [e] [] = return e
-joinR (a:b:es) (op:ops) = do e <- joinR (b:es) ops
-                             return (epos a e (Binop op a e))
-joinR _ _ = fail "Ill-formed binary expression. Report a compiler bug."
-
-getAssoc :: Int -> [(String,CExpr)] -> IParser Assoc
-getAssoc n eops | all (==L) assocs = return L
-                | all (==R) assocs = return R 
-                | all (==N) assocs = case assocs of [_] -> return N
-                                                    _   -> fail msg
-    where levelOps = filter (hasLevel n) eops
-          assocs = map (opAssoc . fst) levelOps
-          msg = concat [ "Conflicting precedence for binary operators ("
-                       , intercalate ", " (map fst eops), "). "
-                       , "Consider adding parentheses to disambiguate." ]
-
diff --git a/compiler/Parse/Declaration.hs b/compiler/Parse/Declaration.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Parse/Declaration.hs
@@ -0,0 +1,134 @@
+
+module Parse.Declaration where
+
+import Control.Applicative ((<$>), (<*>))
+import qualified Data.List as List
+import Text.Parsec hiding (newline,spaces)
+import Text.Parsec.Indent
+import qualified Text.Pandoc as Pan
+
+import Parse.Helpers
+import qualified Parse.Expression as Expr
+import qualified SourceSyntax.Type as T
+import qualified Parse.Type as Type
+import SourceSyntax.Declaration (Declaration(..), Assoc(..))
+
+import Unique
+
+declaration :: IParser (Declaration t v)
+declaration = alias <|> datatype <|> infixDecl <|> foreignDef <|> definition
+
+definition :: IParser (Declaration t v)
+definition = Definition <$> Expr.def
+
+alias :: IParser (Declaration t v)
+alias = do
+  reserved "type" <?> "type alias (type Point = {x:Int, y:Int})"
+  forcedWS
+  alias <- capVar
+  args  <- spacePrefix lowVar
+  whitespace ; string "=" ; whitespace
+  tipe <- Type.expr
+  return (TypeAlias alias args tipe)
+
+datatype :: IParser (Declaration t v)
+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 Type.constructor
+  return $ Datatype name args tcs
+
+
+infixDecl :: IParser (Declaration t v)
+infixDecl = do
+  assoc <- choice [ reserved "infixl" >> return L
+                  , reserved "infix"  >> return N
+                  , reserved "infixr" >> return R ]
+  whitespace
+  n <- digit
+  forcedWS
+  Fixity assoc (read [n]) <$> anyOp
+
+
+foreignDef :: IParser (Declaration t v)
+foreignDef = do
+  try (reserved "foreign")
+  whitespace
+  importEvent <|> exportEvent
+
+exportEvent :: IParser (Declaration t v)
+exportEvent = do
+  try (reserved "export") >> whitespace >> reserved "jsevent" >> whitespace
+  eventName <- jsVar
+  whitespace
+  elmVar <- lowVar
+  whitespace ; hasType ; whitespace
+  tipe <- Type.expr
+  case tipe of
+    T.Data "Signal" [t] ->
+        case isExportable t of
+          Nothing -> return (ExportEvent eventName elmVar tipe)
+          Just err -> error err
+    _ -> error "When importing foreign events, the imported value must have type Signal."
+
+importEvent :: IParser (Declaration t v)
+importEvent = do
+  try (reserved "import") >> whitespace >> reserved "jsevent" >> whitespace
+  eventName <- jsVar
+  whitespace
+  baseValue <- Expr.term <?> "Base case for imported signal (signals cannot be undefined)"
+  whitespace
+  elmVar  <- lowVar <?> "Name of imported signal"
+  whitespace ; hasType ; whitespace
+  tipe <- Type.expr
+  case tipe of
+    T.Data "Signal" [t] ->
+        case isExportable t of
+          Nothing -> return (ImportEvent eventName baseValue elmVar tipe)
+          Just err -> error err
+    _ -> error "When importing foreign events, the imported value must have type Signal."
+
+jsVar :: IParser String
+jsVar = betwixt '"' '"' $ do
+  v <- (:) <$> (letter <|> char '_') <*> many (alphaNum <|> char '_')
+  if v `notElem` jsReserveds then return v else
+      error $ "'" ++ v ++
+          "' is not a good name for a importing or exporting JS values."
+
+jsReserveds :: [String]
+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"
+    ]
+
+isExportable tipe =
+  case tipe of
+    T.Lambda _ _ ->
+        Just $ "Elm's JavaScript event interface does not yet handle functions. " ++
+               "Only simple values can be imported and exported in this release."
+
+    T.Data "JSArray" [t] -> isExportable t
+
+    T.Data name []
+        | any (`List.isSuffixOf` name) jsTypes -> Nothing
+        | otherwise -> Just $ "'" ++ name ++ "' is not an exportable type." ++ msg
+
+    T.Data name _ ->
+        Just $ "'" ++ name ++ "' is not an exportable type " ++
+               "constructor. Only 'JSArray' is an exportable container."
+
+    T.Var _ -> Just $ "Cannot export type variables." ++ msg
+  where
+    msg = " The following types are exportable: " ++ List.intercalate ", " jsTypes
+    jsTypes = ["JSString","JSNumber","JSDomNode","JSBool","JSObject"]
diff --git a/compiler/Parse/Expr.hs b/compiler/Parse/Expr.hs
deleted file mode 100644
--- a/compiler/Parse/Expr.hs
+++ /dev/null
@@ -1,216 +0,0 @@
-module Parse.Expr (def,term) where
-
-import Ast
-import Context
-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"
-
-accessor :: IParser Expr
-accessor = do
-  start <- getPosition
-  lbl <- try (string "." >> rLabel)
-  end <- getPosition
-  let ctx e = addCtx ("." ++ lbl) (pos start end e)
-  return (Lambda "_" (ctx $ Access (ctx $ Var "_") lbl))
-
-
---------  Complex Terms  --------
-
-listTerm :: IParser Expr
-listTerm =
-      (do { try $ string "[markdown|"
-          ; md <- filter (/='\r') <$> manyTill anyChar (try $ string "|]")
-          ; return . Markdown $ Pan.readMarkdown Pan.def md })
-  <|> (braces $ choice
-       [ try $ do { lo <- expr; whitespace; string ".." ; whitespace
-                  ; Range lo <$> expr }
-       , do (C _ _ e) <- list <$> commaSep expr
-            return e
-       ])
-
-parensTerm :: IParser CExpr
-parensTerm = parens $ choice
-             [ do start <- getPosition
-                  op <- try anyOp
-                  end <- getPosition
-                  let ctxt = pos start end
-                  return . ctxt . Lambda "x" . ctxt . Lambda "y" . ctxt $
-                         Binop op (ctxt $ Var "x") (ctxt $ Var "y")
-             , do start <- getPosition
-                  let comma = char ',' <?> "comma ','"
-                  commas <- comma >> many (whitespace >> comma)
-                  end <- getPosition
-                  let vars = map (('v':) . show) [ 0 .. length commas + 1 ]
-                      ctxt = pos start end
-                  return $ foldr (\x e -> ctxt $ Lambda x e)
-                             (ctxt . tuple $ map (ctxt . Var) vars) vars
-             , do start <- getPosition
-                  es <- commaSep expr
-                  end <- getPosition
-                  return $ case es of [e] -> e
-                                      _   -> pos start end (tuple es)
-             ]
-
-recordTerm :: IParser CExpr
-recordTerm = brackets $ choice [ misc, addContext record ]
-    where field = do
-              fDefs <- (:) <$> (PVar <$> rLabel) <*> spacePrefix patternTerm
-              whitespace
-              e <- string "=" >> whitespace >> expr
-              n <- sourceLine <$> getPosition
-              runAt (1000 * n) $ flattenPatterns fDefs e
-          extract [ FnDef f args exp ] = return (f,args,exp)
-          extract _ = fail "Improperly formed record field."
-          record = Record <$> (mapM extract =<< commaSep field)
-          change = do
-              lbl <- rLabel
-              whitespace >> string "<-" >> whitespace
-              (,) lbl <$> expr
-          remove r = addContext (string "-" >> whitespace >> Remove r <$> rLabel)
-          insert r = addContext $ do
-                       string "|" >> whitespace
-                       Insert r <$> rLabel <*>
-                           (whitespace >> string "=" >> whitespace >> expr)
-          modify r = addContext
-                     (string "|" >> whitespace >> Modify r <$> commaSep1 change)
-          misc = try $ do
-            record <- addContext (Var <$> rLabel)
-            whitespace
-            opt <- optionMaybe (remove record)
-            whitespace
-            case opt of
-              Just e  -> try (insert e) <|> return e
-              Nothing -> try (insert record) <|> try (modify record)
-                        
-
-term :: IParser CExpr
-term =  addContext (choice [ numTerm, strTerm, chrTerm, listTerm, accessor ])
-    <|> accessible (addContext varTerm <|> parensTerm <|> recordTerm)
-    <?> "basic term (4, x, 'c', etc.)"
-
---------  Applications  --------
-
-appExpr :: IParser CExpr
-appExpr = do
-  tlist <- spaceSep1 term
-  return $ case tlist of
-             t:[] -> t
-             t:ts -> foldl' (\f x -> epos f x $ App f x) t ts
-
---------  Normal Expressions  --------
-
-binaryExpr :: IParser CExpr
-binaryExpr = binops appExpr anyOp
-
-ifExpr :: IParser Expr
-ifExpr = reserved "if" >> whitespace >> (normal <|> multiIf)
-    where normal = do e1 <- expr ; whitespace
-                      reserved "then" ; whitespace ; e2 <- expr
-                      whitespace <?> "an 'else' branch"
-                      reserved "else" <?> "an 'else' branch" ; whitespace
-                      If e1 e2 <$> expr
-          multiIf = (MultiIf <$> spaceSep1 iff)
-              where iff = do string "|" ; whitespace
-                             b <- expr ; whitespace ; string "->" ; whitespace
-                             (,) b <$> expr
-
-lambdaExpr :: IParser CExpr
-lambdaExpr = do char '\\' <|> char '\x03BB' <?> "anonymous function"
-                whitespace
-                pats <- spaceSep1 patternTerm
-                whitespace ; arrow ; whitespace
-                e <- expr
-                return . run $ makeLambda pats e
-
-defSet :: IParser [Def]
-defSet = concat <$> block (do d <- assignExpr ; whitespace ; return d)
-
-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 = addContext (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
-  n <- sourceLine <$> getPosition
-  runAt (1000 * n) $ flattenPatterns fDefs e
-
-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/compiler/Parse/Expression.hs b/compiler/Parse/Expression.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Parse/Expression.hs
@@ -0,0 +1,242 @@
+module Parse.Expression (def,term) where
+
+import Control.Applicative ((<$>), (<*>))
+import Data.List (foldl')
+import Text.Parsec hiding (newline,spaces)
+import Text.Parsec.Indent
+import qualified Text.Pandoc as Pan
+
+import Parse.Helpers
+import qualified Parse.Pattern as Pattern
+import qualified Parse.Type as Type
+import Parse.Binop
+import Parse.Literal
+
+import SourceSyntax.Location as Location
+import SourceSyntax.Pattern hiding (tuple,list)
+import qualified SourceSyntax.Literal as Literal
+import SourceSyntax.Expression
+import SourceSyntax.Declaration (Declaration(Definition))
+
+import Unique
+
+
+--------  Basic Terms  --------
+
+varTerm :: IParser (Expr t v)
+varTerm = toVar <$> var <?> "variable"
+
+toVar :: String -> Expr t v
+toVar v = case v of "True"  -> Literal (Literal.Boolean True)
+                    "False" -> Literal (Literal.Boolean False)
+                    _       -> Var v
+
+accessor :: IParser (Expr t v)
+accessor = do
+  start <- getPosition
+  lbl <- try (string "." >> rLabel)
+  end <- getPosition
+  let loc e = Location.at start end e
+  return (Lambda (PVar "_") (loc $ Access (loc $ Var "_") lbl))
+
+negative :: IParser (Expr t v)
+negative = do
+  start <- getPosition
+  nTerm <- try (char '-' >> notFollowedBy (char '.' <|> char '-')) >> term
+  end <- getPosition
+  let loc e = Location.at start end e
+  return (Binop "-" (loc $ Literal (Literal.IntNum 0)) nTerm)
+
+
+--------  Complex Terms  --------
+
+listTerm :: IParser (Expr t v)
+listTerm =
+      (do { try $ string "[markdown|"
+          ; md <- filter (/='\r') <$> manyTill anyChar (try $ string "|]")
+          ; return . Markdown $ Pan.readMarkdown Pan.def md })
+  <|> (braces $ choice
+       [ try $ do { lo <- expr; whitespace; string ".." ; whitespace
+                  ; Range lo <$> expr }
+       , ExplicitList <$> commaSep expr
+       ])
+
+parensTerm :: IParser (LExpr t v)
+parensTerm = try (parens opFn) <|> parens (tupleFn <|> parened)
+  where
+    opFn = do
+      start <- getPosition
+      op <- anyOp
+      end <- getPosition
+      let loc = Location.at start end
+      return . loc . Lambda (PVar "x") . loc . Lambda (PVar "y") . loc $
+             Binop op (loc $ Var "x") (loc $ Var "y")
+
+    tupleFn = do
+      start <- getPosition
+      let comma = char ',' <?> "comma ','"
+      commas <- comma >> many (whitespace >> comma)
+      end <- getPosition
+      let vars = map (('v':) . show) [ 0 .. length commas + 1 ]
+          loc = Location.at start end
+      return $ foldr (\x e -> loc $ Lambda x e)
+                 (loc . tuple $ map (loc . Var) vars) (map PVar vars)
+    
+    parened = do
+      start <- getPosition
+      es <- commaSep expr
+      end <- getPosition
+      return $ case es of [e] -> e
+                          _   -> Location.at start end (tuple es)
+
+recordTerm :: IParser (LExpr t v)
+recordTerm = brackets $ choice [ misc, addLocation record ]
+    where field = do
+              label <- rLabel
+              patterns <- spacePrefix Pattern.term
+              whitespace >> string "=" >> whitespace
+              body <- expr
+              return (label, makeFunction patterns body)
+              
+          record = Record <$> commaSep field
+
+          change = do
+              lbl <- rLabel
+              whitespace >> string "<-" >> whitespace
+              (,) lbl <$> expr
+
+          remove r = addLocation (string "-" >> whitespace >> Remove r <$> rLabel)
+
+          insert r = addLocation $ do
+                       string "|" >> whitespace
+                       Insert r <$> rLabel <*>
+                           (whitespace >> string "=" >> whitespace >> expr)
+
+          modify r = addLocation
+                     (string "|" >> whitespace >> Modify r <$> commaSep1 change)
+
+          misc = try $ do
+            record <- addLocation (Var <$> rLabel)
+            whitespace
+            opt <- optionMaybe (remove record)
+            whitespace
+            case opt of
+              Just e  -> try (insert e) <|> return e
+              Nothing -> try (insert record) <|> try (modify record)
+                        
+
+term :: IParser (LExpr t v)
+term =  addLocation (choice [ Literal <$> literal, listTerm, accessor, negative ])
+    <|> accessible (addLocation varTerm <|> parensTerm <|> recordTerm)
+    <?> "basic term (4, x, 'c', etc.)"
+
+--------  Applications  --------
+
+appExpr :: IParser (LExpr t v)
+appExpr = do
+  t <- term
+  ts <- constrainedSpacePrefix term $ \str ->
+            if null str then notFollowedBy (char '-') else return ()
+  return $ case ts of
+             [] -> t
+             _  -> foldl' (\f x -> Location.merge f x $ App f x) t ts
+
+--------  Normal Expressions  --------
+
+binaryExpr :: IParser (LExpr t v)
+binaryExpr = binops [] appExpr lastExpr anyOp
+  where lastExpr = addLocation (choice [ ifExpr, letExpr, caseExpr ])
+                <|> lambdaExpr
+
+ifExpr :: IParser (Expr t v)
+ifExpr = reserved "if" >> whitespace >> (normal <|> multiIf)
+    where
+      normal = do
+        bool <- expr
+        whitespace ; reserved "then" ; whitespace
+        thenBranch <- expr
+        whitespace <?> "an 'else' branch" ; reserved "else" <?> "an 'else' branch" ; whitespace
+        elseBranch <- expr
+        return $ MultiIf [(bool, thenBranch),
+                          (Location.sameAs elseBranch (Var "otherwise"), elseBranch)]
+      multiIf = MultiIf <$> spaceSep1 iff
+          where iff = do string "|" ; whitespace
+                         b <- expr ; whitespace ; string "->" ; whitespace
+                         (,) b <$> expr
+
+lambdaExpr :: IParser (LExpr t v)
+lambdaExpr = do char '\\' <|> char '\x03BB' <?> "anonymous function"
+                whitespace
+                args <- spaceSep1 Pattern.term
+                whitespace ; arrow ; whitespace
+                body <- expr
+                return (makeFunction args body)
+
+defSet :: IParser [Def t v]
+defSet = block (do d <- def ; whitespace ; return d)
+
+letExpr :: IParser (Expr t v)
+letExpr = do
+  reserved "let" ; whitespace
+  defs <- defSet
+  whitespace ; reserved "in" ; whitespace
+  Let defs <$> expr
+
+caseExpr :: IParser (Expr t v)
+caseExpr = do
+  reserved "case"; whitespace; e <- expr; whitespace; reserved "of"; whitespace
+  Case e <$> (with <|> without)
+    where case_ = do p <- Pattern.expr; whitespace; arrow; whitespace
+                     (,) p <$> expr
+          with    = brackets (semiSep1 (case_ <?> "cases { x -> ... }"))
+          without = block (do c <- case_ ; whitespace ; return c)
+
+expr = addLocation (choice [ ifExpr, letExpr, caseExpr ])
+    <|> lambdaExpr
+    <|> binaryExpr 
+    <?> "an expression"
+
+funcDef =
+    choice [ do p1 <- try Pattern.term
+                infics p1 <|> func p1
+           , func =<< (PVar <$> parens symOp)
+           , (:[]) <$> Pattern.expr
+           ] <?> "the definition of a variable (x = ...)"
+    where
+      func pattern =
+          case pattern of
+            PVar v -> (pattern:) <$> spacePrefix Pattern.term
+            _ -> do try (lookAhead (whitespace >> string "="))
+                    return [pattern]
+
+      infics p1 = do
+        o:p <- try (whitespace >> anyOp)
+        p2  <- (whitespace >> Pattern.term)
+        return $ if o == '`' then [ PVar $ takeWhile (/='`') p, p1, p2 ]
+                             else [ PVar (o:p), p1, p2 ]
+
+makeFunction :: [Pattern] -> LExpr t v -> LExpr t v
+makeFunction args body@(L s _) =
+    foldr (\arg body' -> L s $ Lambda arg body') body args
+
+assignExpr :: IParser (Def t v)
+assignExpr = withPos $ do
+  (name:args) <- funcDef
+  whitespace >> string "=" >> whitespace
+  body <- expr
+  return . Def name $ makeFunction args body
+
+typeAnnotation :: IParser (Def t v)
+typeAnnotation = TypeAnnotation <$> try start <*> Type.expr
+    where
+      start = do v <- lowVar <|> parens symOp
+                 whitespace ; hasType ; whitespace
+                 return v
+
+def :: IParser (Def t v)
+def = typeAnnotation <|> assignExpr
+
+attempt f parser str =
+    case iParse parser "" str of
+      Right result -> f result
+      Left err -> error $ "Parse error at " ++ show err
diff --git a/compiler/Parse/Foreign.hs b/compiler/Parse/Foreign.hs
deleted file mode 100644
--- a/compiler/Parse/Foreign.hs
+++ /dev/null
@@ -1,60 +0,0 @@
-
-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
-  hasType          ; whitespace
-  tipe <- typeExpr
-  case tipe of
-    ADTPT "Signal" [pt] ->
-        either error (return . ExportEvent js elm . signalOf) (toForeignType pt)
-    _ -> error "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 ; hasType ; whitespace
-  tipe <- typeExpr
-  case tipe of
-    ADTPT "Signal" [pt] ->
-       either error (return . ImportEvent js base elm . signalOf) (toForeignType pt)
-    _ -> error "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
-      error $ "'" ++ 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/compiler/Parse/Helpers.hs b/compiler/Parse/Helpers.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Parse/Helpers.hs
@@ -0,0 +1,203 @@
+module Parse.Helpers where
+
+import Control.Applicative ((<$>),(<*>))
+import Control.Monad
+import Control.Monad.State
+import Data.Char (isUpper)
+import SourceSyntax.Helpers as Help
+import SourceSyntax.Location as Location
+import SourceSyntax.Expression
+import Text.Parsec hiding (newline,spaces,State)
+import Text.Parsec.Indent
+
+reserveds = [ "if", "then", "else"
+            , "case", "of"
+            , "let", "in"
+            , "data", "type"
+            , "module", "where"
+            , "import", "as", "hiding", "open"
+            , "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")
+
+qualifiedVar :: IParser String
+qualifiedVar = do
+  vars <- many ((++) <$> capVar <*> string ".")
+  (++) (concat vars) <$> lowVar
+
+rLabel :: IParser String
+rLabel = lowVar
+
+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 '`' '`' qualifiedVar <|> symOp <?> "infix operator (e.g. +, *, ||)"
+
+symOp :: IParser String
+symOp = do op <- many1 (satisfy Help.isSymbol)
+           guard (op `notElem` [ "=", "..", "->", "--", "|", "\8594", ":" ])
+           case op of
+             "." -> notFollowedBy lower >> return op
+             "\8728" -> return "."
+             _   -> return op
+
+arrow :: IParser String
+arrow = string "->" <|> string "\8594" <?> "arrow (->)"
+
+hasType :: IParser String
+hasType = string ":" <?> "':' (a type annotation)'"
+
+
+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 (string "::" <?> "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 = constrainedSpacePrefix p (\_ -> return ())
+
+constrainedSpacePrefix p constraint =
+    many . try $ do
+      n <- whitespace
+      constraint n
+      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"
+
+addLocation :: IParser (Expr t v) -> IParser (LExpr t v)
+addLocation expr = do
+  start <- getPosition
+  e <- expr
+  end <- getPosition
+  return (Location.at start end e)
+
+accessible :: IParser (LExpr t v) -> IParser (LExpr t v)
+accessible expr = do
+  start <- getPosition
+  ce@(L _ e) <- expr
+  let rest f = do
+        let dot = char '.' >> notFollowedBy (char '.')
+        access <- optionMaybe (try dot <?> "field access (e.g. List.map)")
+        case access of
+          Nothing -> return ce
+          Just _  -> accessible $ do
+                       v <- var <?> "field access (e.g. List.map)"
+                       end <- getPosition
+                       return (Location.at start end (f v))
+  case e of Var (c:cs) | isUpper c -> rest (\v -> Var (c:cs ++ '.':v))
+                       | otherwise -> rest (Access ce)
+            _ -> rest (Access ce)
+
+
+spaces :: IParser String
+spaces = concat <$> many1 (multiComment <|> string " ") <?> "spaces"
+
+forcedWS :: IParser String
+forcedWS = choice [ try $ (++) <$> spaces <*> (concat <$> many nl_space)
+                  , try $ concat <$> many1 nl_space ]
+    where nl_space = try ((++) <$> (concat <$> many1 newline) <*> spaces)
+
+-- Just eats whitespace until the next meaningful character.
+dumbWhitespace :: IParser String
+dumbWhitespace = concat <$> many (spaces <|> newline)
+
+whitespace :: IParser String
+whitespace = option "" forcedWS <?> "whitespace"
+
+freshLine :: IParser [[String]]
+freshLine = try (many1 newline >> many space_nl) <|> try (many1 space_nl) <?> ""
+    where space_nl = try $ spaces >> many1 newline
+
+newline :: IParser String
+newline = simpleNewline <|> lineComment <?> "newline"
+
+simpleNewline :: IParser String
+simpleNewline = try (string "\r\n") <|> string "\n"
+
+lineComment :: IParser String
+lineComment = do
+  try (string "--")
+  comment <- manyTill anyChar $ simpleNewline <|> (eof >> return "\n")
+  return ("--" ++ comment)
+
+multiComment :: IParser String
+multiComment = do { try (string "{-"); closeComment }
+
+closeComment :: IParser String
+closeComment = do
+    comment <- manyTill anyChar . choice $
+               [ try (string "-}") <?> "close comment"
+               , do { try $ string "{-"; closeComment; closeComment }
+               ]
+    return ("{-" ++ comment ++ "-}")
diff --git a/compiler/Parse/Library.hs b/compiler/Parse/Library.hs
deleted file mode 100644
--- a/compiler/Parse/Library.hs
+++ /dev/null
@@ -1,183 +0,0 @@
-
-module Parse.Library where
-
-import Ast
-import Context
-import Control.Applicative ((<$>),(<*>))
-import Control.Monad
-import Control.Monad.State
-import Data.Char (isUpper)
-import Rename (deprime)
-import Text.Parsec hiding (newline,spaces,State)
-import Text.Parsec.Indent
-
-reserveds = [ "if", "then", "else"
-            , "case", "of"
-            , "let", "in"
-            , "data", "type"
-            , "module", "where"
-            , "import", "as", "hiding", "open"
-            , "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")
-
-rLabel :: IParser String
-rLabel = deprime <$> lowVar
-
-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. +, *, ||)"
-
-symOp :: IParser String
-symOp = do op <- many1 (satisfy isOp)
-           guard (op `notElem` [ "=", "..", "->", "--", "|", "\8594", ":" ])
-           case op of
-             "." -> notFollowedBy lower >> return op
-             "\8728" -> return "."
-             _   -> return op
-
-arrow :: IParser String
-arrow = string "->" <|> string "\8594" <?> "arrow (->)"
-
-hasType :: IParser String
-hasType = string ":" <?> "':' (a type annotation)'"
-
-
-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 (string "::" <?> "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"
-
-addContext :: IParser Expr -> IParser CExpr
-addContext expr = do
-  start <- getPosition
-  e <- expr
-  end <- getPosition
-  return (pos start end e)
-
-accessible :: IParser CExpr -> IParser CExpr
-accessible expr = do
-  start <- getPosition
-  ce@(C s t e) <- expr
-  let rest f = do
-        let dot = char '.' >> notFollowedBy (char '.')
-        access <- optionMaybe (try dot <?> "field access (e.g. List.map)")
-        case access of
-          Nothing -> return ce
-          Just _  -> accessible $ do
-                       v <- var <?> "field access (e.g. List.map)"
-                       end <- getPosition
-                       return (pos start end (f v))
-  case e of Var (c:cs) | isUpper c -> rest (\v -> Var (c:cs ++ '.':v))
-                       | otherwise -> rest (Access ce)
-            _ -> rest (Access ce)
-
-
-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 (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/compiler/Parse/Literal.hs b/compiler/Parse/Literal.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Parse/Literal.hs
@@ -0,0 +1,43 @@
+module Parse.Literal (literal) where
+
+import Control.Applicative ((<$>), (<*>))
+import Control.Monad
+import Text.Parsec hiding (newline,spaces)
+import Text.Parsec.Indent
+
+import Parse.Helpers
+import SourceSyntax.Literal
+
+literal = num <|> str <|> chr
+
+num :: IParser Literal
+num = fmap toLit (preNum <?> "number")
+    where toLit n | '.' `elem` n = FloatNum (read n)
+                  | otherwise = IntNum (read n)
+          preNum  = (++) <$> many1 digit <*> option "" postNum
+          postNum = do try $ lookAhead (string "." >> digit)
+                       string "."
+                       ('.':) <$> many1 digit
+
+chr :: IParser Literal
+chr = Chr <$> betwixt '\'' '\'' (backslashed <|> satisfy (/='\''))
+      <?> "character"
+
+str :: IParser Literal
+str = choice [ quote >> str <$> manyTill (backslashed <|> anyChar) quote
+             , liftM Str . expecting "string" . betwixt '"' '"' . many $
+               backslashed <|> satisfy (/='"')
+             ]
+    where
+      quote = try (string "\"\"\"")
+      str = Str . dewindows
+
+      -- Remove \r from strings to fix generated JavaScript
+      dewindows [] = []
+      dewindows cs =
+          let (pre, suf) = break (`elem` ['\r','\n']) cs
+          in  pre ++ case suf of 
+                       ('\r':'\n':rest) -> '\n' : dewindows rest
+                       ('\n':rest)      -> '\n' : dewindows rest
+                       ('\r':rest)      -> '\n' : dewindows rest
+                       _                -> []
diff --git a/compiler/Parse/Module.hs b/compiler/Parse/Module.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Parse/Module.hs
@@ -0,0 +1,55 @@
+
+module Parse.Module (moduleDef, getModuleName, imports) where
+
+import Control.Applicative ((<$>), (<*>))
+import Data.List (intercalate)
+import Text.Parsec hiding (newline,spaces)
+
+import Parse.Helpers
+import SourceSyntax.Module (Module(..), ImportMethod(..), Imports)
+
+varList ::  IParser [String]
+varList = parens $ commaSep1 (var <|> parens symOp)
+
+getModuleName :: String -> Maybe String
+getModuleName source =
+    case iParse getModuleName "" source of
+      Right name -> Just name
+      Left _     -> Nothing
+    where
+      getModuleName = do
+        optional freshLine
+        (names, _) <- moduleDef
+        return (intercalate "." names)
+
+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
+     open <- optionMaybe (reserved "open")
+     whitespace
+     name <- intercalate "." <$> dotSep1 capVar
+     case open of
+       Just _ -> return (name, Hiding [])
+       Nothing -> let how = try (whitespace >> (as' <|> importing'))
+                  in  (,) name <$> option (As name) how
+  where
+    as' :: IParser ImportMethod
+    as' = reserved "as" >> whitespace >> As <$> capVar <?> "alias for module"
+
+    importing' :: IParser ImportMethod
+    importing' = Importing <$> varList <?> "listing of imported values (x,y,z)"
diff --git a/compiler/Parse/Modules.hs b/compiler/Parse/Modules.hs
deleted file mode 100644
--- a/compiler/Parse/Modules.hs
+++ /dev/null
@@ -1,46 +0,0 @@
-
-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
-  open <- optionMaybe (reserved "open")
-  whitespace
-  name <- intercalate "." <$> dotSep1 capVar
-  case open of
-    Just _ -> return (name, Hiding [])
-    Nothing -> let how = try (whitespace >> (as' <|> importing'))
-               in  (,) name <$> option (Importing []) how
-
-
-as' :: IParser ImportMethod
-as' = reserved "as" >> whitespace >> As <$> capVar <?> "alias for module"
-
-importing' :: IParser ImportMethod
-importing' = Importing <$> varList <?> "listing of imported values (x,y,z)"
diff --git a/compiler/Parse/Parse.hs b/compiler/Parse/Parse.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Parse/Parse.hs
@@ -0,0 +1,47 @@
+module Parse.Parse (program, dependencies) where
+
+import Control.Applicative ((<$>), (<*>))
+import Control.Monad
+import Data.Char (isSymbol, isDigit)
+import Data.List (foldl',intercalate)
+import Text.Parsec hiding (newline,spaces)
+import qualified Text.PrettyPrint as P
+
+import qualified SourceSyntax.Module as S
+import Parse.Helpers
+import Parse.Binop (infixStmt, OpTable)
+import Parse.Expression
+import Parse.Type
+import Parse.Module
+import qualified Parse.Declaration as Decl
+
+freshDef = commitIf (freshLine >> (letter <|> char '_')) $ do
+             freshLine
+             Decl.declaration <?> "another datatype or variable definition"
+
+decls = do d <- Decl.declaration <?> "at least one datatype or variable definition"
+           (d:) <$> many freshDef
+
+program :: String -> Either [P.Doc] (S.Module t v)
+program = setupParser $ do
+  optional freshLine
+  (names,exports) <- option (["Main"],[]) (moduleDef `followedBy` freshLine)
+  is <- (do try (lookAhead $ reserved "import")
+            imports `followedBy` freshLine) <|> return []
+  declarations <- decls
+  optional freshLine ; optional spaces ; eof
+  return $ S.Module names exports is declarations
+
+dependencies :: String -> Either [P.Doc] (String, [String])
+dependencies =
+    let getName = intercalate "." . fst in
+    setupParser $ do
+      optional freshLine
+      (,) <$> option "Main" (getName <$> moduleDef `followedBy` freshLine)
+          <*> option [] (map fst <$> imports `followedBy` freshLine)
+
+setupParser :: IParser a -> String -> Either [P.Doc] a
+setupParser p source =
+    case iParse p "" source of
+      Right result -> Right result
+      Left err -> Left [ P.text $ "Parse error at " ++ show err ]
diff --git a/compiler/Parse/Parser.hs b/compiler/Parse/Parser.hs
deleted file mode 100644
--- a/compiler/Parse/Parser.hs
+++ /dev/null
@@ -1,52 +0,0 @@
-module Parse.Parser (parseProgram, preParse) where
-
-import Ast
-import Control.Applicative ((<$>), (<*>))
-import Control.Monad
-import Data.Char (isSymbol, isDigit)
-import Data.List (foldl',intercalate)
-import Text.Parsec hiding (newline,spaces)
-
-import Parse.Library
-import Parse.Expr
-import Parse.Types
-import Parse.Modules
-import Parse.Foreign
-
-
-statement = choice (typeAlias:defs) <|> def <?> "datatype or variable definition"
-    where defs = map ((:[]) <$>) [ foreignDef, datatype, typeAnnotation ]
-
-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 = setupParser program
-
-preParse :: String -> Either String (String, [String])
-preParse = setupParser $ do
-             optional skip
-             (,) <$> option "Main" moduleName <*> option [] imprts
-    where 
-      skip = try (manyTill anyChar (try (string "/**")))
-      imprts = fmap (map fst) imports `followedBy` freshLine
-      getName = intercalate "." . fst
-      moduleName = do optional freshLine 
-                      getName <$> moduleDef `followedBy` freshLine
-
-setupParser p source =
-    case iParse p "" source of
-      Right result -> Right result
-      Left err -> Left $ "Parse error at " ++ show err
diff --git a/compiler/Parse/Pattern.hs b/compiler/Parse/Pattern.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Parse/Pattern.hs
@@ -0,0 +1,134 @@
+
+module Parse.Pattern (term, expr) where
+
+import Control.Applicative ((<$>),(<*>),pure)
+import Control.Monad
+import Control.Monad.State
+import Data.Char (isUpper)
+import Data.List (intercalate)
+import Unique
+import Text.Parsec hiding (newline,spaces,State)
+import Text.Parsec.Indent
+
+import Parse.Helpers
+import Parse.Literal
+import qualified SourceSyntax.Pattern as Pattern
+import SourceSyntax.Everything hiding (tuple)
+
+
+basic :: IParser Pattern
+basic = choice
+    [ char '_' >> return PAnything
+    , do v <- var
+         return $ case v of
+                    "True"  -> PLiteral (Boolean True)
+                    "False" -> PLiteral (Boolean False)
+                    c : _   -> if isUpper c then PData v [] else PVar v
+    , do lit <- literal
+         return $ case lit of
+                    Str s -> foldr combine (PData "[]" []) s
+                       where combine h t = PData "::" [PLiteral (Chr h),t]
+                    _ -> PLiteral lit
+    ]
+
+asPattern :: Pattern -> IParser Pattern
+asPattern pattern = do
+  var <- optionMaybe (try (whitespace >> reserved "as" >> whitespace >> lowVar))
+  return $ case var of
+             Just v -> PAlias v pattern
+             Nothing -> pattern
+
+record :: IParser Pattern
+record = PRecord <$> brackets (commaSep1 lowVar)
+
+tuple :: IParser Pattern
+tuple = do ps <- parens (commaSep expr)
+           return $ case ps of { [p] -> p; _ -> Pattern.tuple ps }
+
+list :: IParser Pattern
+list = Pattern.list <$> braces (commaSep expr)
+
+term :: IParser Pattern
+term =
+     (choice [ record, tuple, list, basic ]) <?> "pattern"
+
+patternConstructor :: IParser Pattern
+patternConstructor = do
+  v <- intercalate "." <$> dotSep1 capVar
+  case v of
+    "True"  -> return $ PLiteral (Boolean True)
+    "False" -> return $ PLiteral (Boolean False)
+    _       -> PData v <$> spacePrefix term
+
+expr :: IParser Pattern
+expr = do
+  patterns <- consSep1 (patternConstructor <|> term)
+  asPattern (foldr1 Pattern.cons patterns) <?> "pattern"
+
+{--
+extract :: Pattern -> LExpr t v -> Unique (String, LExpr t v)
+extract pattern body@(L t s _) =
+  let loc = L t s in
+  let fn x e = (x,e) in
+  case pattern of
+    PAnything -> return $ fn "_" body
+    PVar x -> return $ fn x body
+    PAlias x PAnything -> return $ fn x body
+    PAlias x p -> do
+      (x', body') <- extract p body
+      return $ fn x (loc $ Let [FnDef x' [] (loc $ Var x)] body')
+    PData name ps -> do
+        x <- guid
+        let a = '_' : show x
+        return . fn a . loc $ Case (loc (Var a)) [(pattern, body)]
+    PRecord fs -> do
+        x <- guid
+        let a = '_' : show x
+            toDef f = FnDef f [] (loc $ Access (loc $ Var a) f)
+        return . fn a . loc $ Let (map toDef fs) body
+
+extracts :: [Pattern] -> LExpr t v -> Unique ([String], LExpr t v)
+extracts ps body = go [] (reverse ps) body
+    where go args [] body = return (args, body)
+          go args (p:ps) body = do (x,e) <- extract p body
+                                   go (x:args) ps e
+
+flatten :: [Pattern] -> LExpr t v -> Unique (IParser [Def t v])
+flatten patterns exp@(L t s _) =
+  let loc = L t s in
+  case patterns of
+    PVar f : args -> do
+        (as,e) <- extracts args exp
+        return . return $
+               if isOp (head f) then let [a,b] = as in [ OpDef f a b e ]
+                                else [ FnDef f as e ]
+
+    [p] -> return `liftM` matchSingle p exp p
+
+    _ -> return . fail $ "Pattern (" ++ unwords (map show patterns) ++
+                ") cannot be used on the left-hand side of an assign statement."
+
+matchSingle :: Pattern -> LExpr t v -> Pattern -> Unique [Def t v]
+matchSingle pat exp@(L t s _) p =
+  let loc = L t s in
+  case p of
+    PData _ ps -> do
+        x <- guid
+        let v = '_' : show x
+        dss <- mapM (matchSingle pat . loc $ Var v) ps
+        return (FnDef v [] exp : concat dss)
+
+    PVar x ->
+        return [ FnDef x [] (loc $ Case exp [(pat, loc $ Var x)]) ]
+
+    PAlias x p' -> do
+        subPat <- matchSingle p' (loc $ Var x) p'
+        return $ (FnDef x [] (loc $ Case exp [(pat, loc $ Var x)])):subPat
+      
+    PRecord fs -> do
+        a <- (\x -> '_' : show x) `liftM` guid
+        let toDef f = FnDef f [] (loc $ Access (loc $ Var a) f)
+        return (FnDef a [] exp : map toDef fs)
+
+    PAnything -> return []
+--}
diff --git a/compiler/Parse/Patterns.hs b/compiler/Parse/Patterns.hs
deleted file mode 100644
--- a/compiler/Parse/Patterns.hs
+++ /dev/null
@@ -1,105 +0,0 @@
-
-module Parse.Patterns (patternTerm, patternExpr, makeLambda, flattenPatterns) where
-
-import Ast
-import Context
-import Control.Applicative ((<$>),(<*>))
-import Control.Monad
-import Control.Monad.State
-import Data.Char (isUpper)
-import Guid
-import Text.Parsec hiding (newline,spaces,State)
-import Text.Parsec.Indent
-import Parse.Library
-
-patternBasic :: IParser Pattern
-patternBasic =
-    choice [ char '_' >> return PAnything
-           , do x@(c:_) <- var
-                return $ if isUpper c then PData x [] else PVar x
-           ]
-
-patternRecord :: IParser Pattern
-patternRecord = PRecord <$> brackets (commaSep1 lowVar)
-
-patternTuple :: IParser Pattern
-patternTuple = do ps <- parens (commaSep patternExpr)
-                  return $ case ps of { [p] -> p; _ -> ptuple ps }
-
-patternList :: IParser Pattern
-patternList = plist <$> braces (commaSep patternExpr)
-
-patternTerm :: IParser Pattern
-patternTerm = choice [ patternRecord, patternTuple, patternList, patternBasic ]
-           <?> "pattern"
-
-patternConstructor :: IParser Pattern
-patternConstructor = PData <$> capVar <*> spacePrefix patternTerm
-
-patternExpr :: IParser Pattern
-patternExpr = foldr1 pcons <$> consSep1 (patternConstructor <|> patternTerm) <?> "pattern"
-
-makeLambda :: [Pattern] -> CExpr -> GuidCounter CExpr
-makeLambda pats body = go (reverse pats) body
-    where go [] body = return body
-          go (p:ps) body@(C t s _) = do
-            (x,e) <- extract p body
-            go ps (C t s $ Lambda x e)
-          
-extract :: Pattern -> CExpr -> GuidCounter (String, CExpr)
-extract pattern body@(C t s _) =
-  let ctx = C t s in
-  let fn x e = (x,e) in
-  case pattern of
-    PAnything -> return $ fn "_" body
-    PVar x -> return $ fn x body
-    PData name ps -> do
-        x <- guid
-        let a = '_' : show x
-        return . fn a . ctx $ Case (ctx (Var a)) [(pattern, body)]
-    PRecord fs -> do
-        x <- guid
-        let a = '_' : show x
-            toDef f = FnDef f [] (ctx $ Access (ctx $ Var a) f)
-        return . fn a . ctx $ Let (map toDef fs) body
-
-extracts :: [Pattern] -> CExpr -> GuidCounter ([String], CExpr)
-extracts ps body = go [] (reverse ps) body
-    where go args [] body = return (args, body)
-          go args (p:ps) body = do (x,e) <- extract p body
-                                   go (x:args) ps e
-
-flattenPatterns :: [Pattern] -> CExpr -> GuidCounter (IParser [Def])
-flattenPatterns patterns exp@(C t s _) =
-  let ctx = C t s in
-  case patterns of
-    PVar f : args -> do
-        (as,e) <- extracts args exp
-        return . return $
-               if isOp (head f) then let [a,b] = as in [ OpDef f a b e ]
-                                else [ FnDef f as e ]
-
-    [p] -> return `liftM` matchSingle p exp p
-
-    _ -> return . fail $ "Pattern (" ++ unwords (map show patterns) ++
-                ") cannot be used on the left-hand side of an assign statement."
-
-matchSingle :: Pattern -> CExpr -> Pattern -> GuidCounter [Def]
-matchSingle pat exp@(C t s _) p =
-  let ctx = C t s in
-  case p of
-    PData _ ps -> do
-        x <- guid
-        let v = '_' : show x
-        dss <- mapM (matchSingle pat . ctx $ Var v) ps
-        return (FnDef v [] exp : concat dss)
-
-    PVar x ->
-        return [ FnDef x [] (ctx $ Case exp [(pat, ctx $ Var x)]) ]
-
-    PRecord fs -> do
-        a <- (\x -> '_' : show x) `liftM` guid
-        let toDef f = FnDef f [] (ctx $ Access (ctx $ Var a) f)
-        return (FnDef a [] exp : map toDef fs)
-
-    PAnything -> return []
diff --git a/compiler/Parse/Type.hs b/compiler/Parse/Type.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Parse/Type.hs
@@ -0,0 +1,81 @@
+module Parse.Type where
+
+import Control.Applicative ((<$>),(<*>))
+import Control.Monad (liftM,mapM)
+import Data.Char (isLower)
+import Data.List (lookup,intercalate)
+import Text.Parsec
+import Text.Parsec.Indent
+
+import SourceSyntax.Type as T
+import Parse.Helpers
+import Unique
+
+tvar :: IParser T.Type
+tvar = T.Var <$> lowVar <?> "type variable"
+
+list :: IParser T.Type
+list = listOf <$> braces expr
+
+tuple :: IParser T.Type
+tuple = do ts <- parens (commaSep expr)
+           return $ case ts of
+                      [t] -> t
+                      _   -> tupleOf ts
+
+record :: IParser T.Type
+record =
+  do char '{' ; whitespace
+     ext <- extend
+     fs <- fields
+     dumbWhitespace ; char '}'
+     return (T.Record fs ext)
+  where
+    extend = option T.EmptyRecord . try $ do
+               t <- tvar
+               whitespace >> string "|" >> whitespace
+               return t
+    fields = commaSep $ do
+               lbl <- rLabel
+               whitespace >> hasType >> whitespace
+               (,) lbl <$> expr
+
+capTypeVar = intercalate "." <$> dotSep1 capVar
+
+constructor0 :: IParser T.Type
+constructor0 =
+  do name <- capTypeVar
+     return (T.Data name [])
+
+term :: IParser T.Type
+term = list <|> tuple <|> record <|> tvar <|> constructor0
+
+app :: IParser T.Type
+app =
+  do name <- capTypeVar <|> try tupleCtor <?> "type constructor"
+     args <- spacePrefix term
+     return (T.Data name args)
+  where
+    tupleCtor = do
+      n <- length <$> parens (many (char ','))
+      return $ "_Tuple" ++ show (if n == 0 then 0 else n+1)
+
+expr :: IParser T.Type
+expr =
+  do t1 <- app <|> term
+     whitespace
+     arr <- optionMaybe arrow
+     whitespace
+     case arr of
+       Just _  -> T.Lambda t1 <$> expr
+       Nothing -> return t1
+
+constructor :: IParser (String, [T.Type])
+constructor = (,) <$> (capTypeVar <?> "another type constructor")
+                  <*> spacePrefix term
+
+readType :: String -> Type
+readType str =
+    case iParse expr "" str of
+      Left err -> error (show err)
+      Right tipe -> tipe
diff --git a/compiler/Parse/Types.hs b/compiler/Parse/Types.hs
deleted file mode 100644
--- a/compiler/Parse/Types.hs
+++ /dev/null
@@ -1,170 +0,0 @@
-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,intercalate)
-import Text.Parsec
-import Text.Parsec.Indent
-
-import Context
-import Parse.Library
-import Types.Types hiding (parens,string)
-import Guid
-
-data ParseType = VarPT String
-               | LambdaPT ParseType ParseType
-               | ADTPT String [ParseType]
-               | RecordPT (Maybe ParseType) [(String,ParseType)]
-                 deriving (Show)
-
-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 }
-
-typeRecord :: IParser ParseType
-typeRecord = brackets (RecordPT <$> extend <*> fields)
-  where extend = optionMaybe . try $ do
-                   t <- typeVar
-                   whitespace >> string "|" >> whitespace
-                   return t
-        fields = commaSep $ do
-                   lbl <- rLabel
-                   whitespace >> hasType >> whitespace
-                   (,) lbl <$> typeExpr
-
-typeUnambiguous :: IParser ParseType
-typeUnambiguous = typeList <|> typeTuple <|> typeRecord
-
-typeSimple :: IParser ParseType
-typeSimple = VarPT <$> var
-
-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)
-
-typeAlias :: IParser [Statement]
-typeAlias = do
-  start <- getPosition
-  reserved "type" <?> "type alias (type Point = {x:Int, y:Int})"
-  forcedWS
-  alias <- capVar
-  args  <- spacePrefix lowVar
-  whitespace ; string "=" ; whitespace
-  let n = length args
-  tipe <- typeExpr
-  end <- getPosition
-  case toTypeWith alias (zip args [1..n]) tipe of
-    Left msg -> fail msg
-    Right t -> return (TypeAlias alias [1..n] t : ctor)
-        where ctor = case tipe of
-                       RecordPT _ kvs -> [toConstructor start end alias kvs]
-                       _ -> []
-
-toConstructor start end alias kvs =
-    Definition (FnDef alias args (ctxt (Record rec)))
-  where
-    ctxt = pos start end
-    args = map fst kvs
-    rec = map (\a -> (a, [], ctxt (Var a))) args
-
-
-typeAnnotation :: IParser Statement
-typeAnnotation = TypeAnnotation <$> try start <*> (toType <$> typeExpr)
-    where start = do v <- lowVar <|> parens symOp
-                     whitespace ; hasType ; whitespace ; return v
-
-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
-
-toType :: ParseType -> Type
-toType pt =
-  let frees :: ParseType -> [String]
-      frees pt = case pt of
-                   LambdaPT a b  -> frees a ++ frees b
-                   ADTPT _ ts    -> concatMap frees ts
-                   RecordPT t fs -> maybe [] frees t ++ concatMap (frees . snd) fs
-                   VarPT (c:cs) | isLower c -> [c:cs]
-                                | otherwise -> []
-  in  case toTypeWith "" (zip (frees pt) [1..]) pt of
-        Right t -> t
-        Left  _ -> VarT 0
-
-toTypeWith :: String -> [(String,X)] -> ParseType -> Either String Type
-toTypeWith name tvarDict pt =
-  let msg x = "Type variable '" ++ x ++ "' is unbound in type '" ++ name ++ "'."
-      toT = toTypeWith name tvarDict
-  in  case pt of
-        LambdaPT t1 t2  -> (==>) <$> toT t1 <*> toT t2
-        ADTPT name args -> ADT name <$> mapM toT args
-        RecordPT t fs   -> do fs' <- mapM (\(x,pt) -> (,) x <$> toT pt) fs
-                              ext <- maybe (return EmptyRecord) toT t
-                              return (RecordT (recordT fs') ext)
-        VarPT x@(c:_)
-            | not (isLower c) -> return $ ADT x []
-            | otherwise -> VarT <$> case lookup x tvarDict of
-                                      Just v -> Right v
-                                      Nothing -> Left (msg x)
-
-
-toDatatype name args tcs = Datatype name [1..n] <$> mapM toC tcs
-    where n = length args
-          toType = toTypeWith name (zip args [1..n])
-          toC (name,pt) = (,) name <$> mapM toType pt
-
-
-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."
-
-toForeignType (ADTPT "JSArray" args) =
-    ADT "JSArray" <$> mapM toForeignType args
-
-toForeignType (ADTPT name _) =
-    Left $ "'" ++ name ++ "' is not an exportable type " ++
-             "constructor. Only 'JSArray' is exportable."
-
-toForeignType (VarPT x@(c:_))
-    | x `elem` jsTypes = Right (ADT x [])
-    | isLower c =
-        Left $ "All exported types must be concrete types." ++ msg
-    | otherwise =
-        Left $ "'" ++ x ++ "' is not an exportable type." ++ msg
-  where
-    msg = " The following types are exportable: " ++ intercalate ", " jsTypes
-    jsTypes = ["JSString","JSNumber","JSDomNode","JSBool","JSObject"]
diff --git a/compiler/SourceSyntax/Declaration.hs b/compiler/SourceSyntax/Declaration.hs
new file mode 100644
--- /dev/null
+++ b/compiler/SourceSyntax/Declaration.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module SourceSyntax.Declaration where
+
+import Data.Data
+import qualified SourceSyntax.Expression as Expr
+import SourceSyntax.Type
+
+data Declaration tipe var
+    = Definition (Expr.Def tipe var)
+    | Datatype String [String] [(String,[Type])]
+    | TypeAlias String [String] Type
+    | ImportEvent String (Expr.LExpr tipe var) String Type
+    | ExportEvent String String Type
+    | Fixity Assoc Int String
+      deriving (Eq, Show)
+
+data Assoc = L | N | R
+             deriving (Eq, Show)
diff --git a/compiler/SourceSyntax/Everything.hs b/compiler/SourceSyntax/Everything.hs
new file mode 100644
--- /dev/null
+++ b/compiler/SourceSyntax/Everything.hs
@@ -0,0 +1,17 @@
+module SourceSyntax.Everything
+    (module SourceSyntax.Helpers,
+     module SourceSyntax.Location,
+     module SourceSyntax.Literal,
+     module SourceSyntax.Pattern,
+     module SourceSyntax.Expression,
+     module SourceSyntax.Declaration,
+     module SourceSyntax.Module
+    ) where
+
+import SourceSyntax.Helpers
+import SourceSyntax.Location
+import SourceSyntax.Literal
+import SourceSyntax.Pattern hiding (tuple, list, cons, nil, prettyParens)
+import SourceSyntax.Expression
+import SourceSyntax.Declaration hiding (Assoc(..))
+import SourceSyntax.Module
diff --git a/compiler/SourceSyntax/Expression.hs b/compiler/SourceSyntax/Expression.hs
new file mode 100644
--- /dev/null
+++ b/compiler/SourceSyntax/Expression.hs
@@ -0,0 +1,130 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module SourceSyntax.Expression where
+
+import Data.Data
+import Data.List (intercalate)
+import qualified Text.Pandoc as Pandoc
+import SourceSyntax.PrettyPrint
+import Text.PrettyPrint as P
+import qualified SourceSyntax.Helpers as Help
+import qualified SourceSyntax.Location as Location
+import qualified SourceSyntax.Pattern as Pattern
+import qualified SourceSyntax.Type as Type
+import qualified SourceSyntax.Literal as Literal
+
+type LExpr tipe var = Location.Located (Expr tipe var)
+data Expr t v
+    = Literal Literal.Literal
+    | Var String
+    | Range (LExpr t v) (LExpr t v)
+    | ExplicitList [LExpr t v]
+    | Binop String (LExpr t v) (LExpr t v)
+    | Lambda Pattern.Pattern (LExpr t v)
+    | App (LExpr t v) (LExpr t v)
+    | MultiIf [(LExpr t v,LExpr t v)]
+    | Let [Def t v] (LExpr t v)
+    | Case (LExpr t v) [(Pattern.Pattern, LExpr t v)]
+    | Data String [LExpr t v]
+    | Access (LExpr t v) String
+    | Remove (LExpr t v) String
+    | Insert (LExpr t v) String (LExpr t v)
+    | Modify (LExpr t v) [(String, LExpr t v)]
+    | Record [(String, LExpr t v)]
+    | Markdown Pandoc.Pandoc
+      deriving (Eq, Show, Data, Typeable)
+
+data Def tipe var
+    = Def Pattern.Pattern (LExpr tipe var)
+    | TypeAnnotation String Type.Type
+      deriving (Eq, Show, Data, Typeable)
+
+tuple es = Data ("_Tuple" ++ show (length es)) es
+
+delist (Location.L _ (Data "::" [h,t])) = h : delist t
+delist _ = []
+
+saveEnvName = "_save_the_environment!!!"
+
+dummyLet defs = 
+     Location.none $ Let defs (Location.none $ Var saveEnvName)
+
+instance Pretty (Expr t v) where
+  pretty expr =
+   case expr of
+     Literal lit -> pretty lit
+     Var x -> variable x
+     Range e1 e2 -> P.brackets (pretty e1 <> P.text ".." <> pretty e2)
+     ExplicitList es -> P.brackets (commaCat (map pretty es))
+     Binop op e1 e2 -> P.sep [ prettyParens e1 <+> P.text op', prettyParens e2 ]
+         where op' = if Help.isOp op then op else "`" ++ op ++ "`"
+     Lambda p e -> let (ps,body) = collectLambdas (Location.none $ Lambda p e)
+                   in  P.text "\\" <> P.sep ps <+> P.text "->" <+> pretty body
+     App _ _ -> P.hang func 2 (P.sep args)
+         where func:args = map prettyParens (collectApps (Location.none expr))
+     MultiIf branches ->  P.text "if" $$ nest 3 (vcat $ map iff branches)
+         where
+           iff (b,e) = P.text "|" <+> P.hang (pretty b <+> P.text "->") 2 (pretty e)
+     Let defs e ->
+         P.sep [ P.hang (P.text "let") 4 (P.vcat (map pretty defs))
+               , P.text "in" <+> pretty e ]
+     Case e pats ->
+         P.hang pexpr 2 (P.vcat (map pretty' pats))
+         where
+           pexpr = P.sep [ P.text "case" <+> pretty e, P.text "of" ]
+           pretty' (p,e) = pretty p <+> P.text "->" <+> pretty e
+     Data "::" [hd,tl] -> pretty hd <+> P.text "::" <+> pretty tl
+     Data "[]" [] -> P.text "[]"
+     Data name es -> P.hang (P.text name) 2 (P.sep (map prettyParens es))
+     Access e x -> prettyParens e <> P.text "." <> P.text x
+     Remove e x -> P.braces (pretty e <+> P.text "-" <+> P.text x)
+     Insert (Location.L _ (Remove e y)) x v ->
+         P.braces (pretty e <+> P.text "-" <+> P.text y <+> P.text "|" <+> P.text x <+> P.text "=" <+> pretty v)
+     Insert e x v ->
+         P.braces (pretty e <+> P.text "|" <+> P.text x <+> P.text "=" <+> pretty v)
+
+     Modify e fs ->
+         P.braces $ P.hang (pretty e <+> P.text "|")
+                           4
+                           (commaSep $ map field fs)
+       where
+         field (x,e) = P.text x <+> P.text "<-" <+> pretty e
+
+     Record fs ->
+         P.braces $ P.nest 2 (commaSep $ map field fs)
+       where
+         field (x,e) = P.text x <+> P.text "=" <+> pretty e
+
+     Markdown _ -> P.text "[markdown| ... |]"
+
+instance Pretty (Def t v) where
+  pretty def =
+   case def of
+     TypeAnnotation name tipe ->
+         variable name <+> P.text ":" <+> pretty tipe
+     Def pattern expr ->
+         pretty pattern <+> P.text "=" <+> pretty expr
+
+collectApps lexpr@(Location.L _ expr) =
+  case expr of
+    App a b -> collectApps a ++ [b]
+    _ -> [lexpr]
+
+collectLambdas lexpr@(Location.L _ expr) =
+  case expr of
+    Lambda pattern body ->
+        let (ps, body') = collectLambdas body
+        in  (pretty pattern : ps, body')
+    _ -> ([], lexpr)
+
+prettyParens (Location.L _ expr) = parensIf needed (pretty expr)
+  where
+    needed =
+      case expr of
+        Binop _ _ _ -> True
+        Lambda _ _  -> True
+        App _ _     -> True
+        MultiIf _   -> True
+        Let _ _     -> True
+        Case _ _    -> True
+        Data name (x:xs) -> name /= "::"
+        _ -> False
diff --git a/compiler/SourceSyntax/Helpers.hs b/compiler/SourceSyntax/Helpers.hs
new file mode 100644
--- /dev/null
+++ b/compiler/SourceSyntax/Helpers.hs
@@ -0,0 +1,18 @@
+
+module SourceSyntax.Helpers where
+
+import qualified Data.Char as Char
+
+brkt :: String -> String
+brkt s = "{ " ++ s ++ " }"
+
+isTuple :: String -> Bool
+isTuple name =
+    take 6 name == "_Tuple" && all Char.isDigit (drop 6 name)
+
+isOp :: String -> Bool
+isOp = all isSymbol
+
+isSymbol :: Char -> Bool
+isSymbol c =
+    Char.isSymbol c || elem c "+-/*=.$<>:&|^?%#@~!"
diff --git a/compiler/SourceSyntax/Literal.hs b/compiler/SourceSyntax/Literal.hs
new file mode 100644
--- /dev/null
+++ b/compiler/SourceSyntax/Literal.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module SourceSyntax.Literal where
+
+import Data.Data
+import SourceSyntax.PrettyPrint
+import qualified Text.PrettyPrint as PP
+
+data Literal = IntNum Int
+             | FloatNum Float
+             | Chr Char
+             | Str String
+             | Boolean Bool
+               deriving (Eq, Ord, Data, Typeable, Show)
+
+instance Pretty Literal where
+  pretty literal =
+    case literal of
+      IntNum n -> PP.int n
+      FloatNum n -> PP.float n
+      Chr c -> PP.quotes (PP.char c)
+      Str s -> PP.text (show s)
+      Boolean bool -> PP.text (show bool)
diff --git a/compiler/SourceSyntax/Location.hs b/compiler/SourceSyntax/Location.hs
new file mode 100644
--- /dev/null
+++ b/compiler/SourceSyntax/Location.hs
@@ -0,0 +1,60 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module SourceSyntax.Location where
+
+import Data.Data
+import Text.PrettyPrint
+import SourceSyntax.PrettyPrint
+import qualified Text.Parsec.Pos as Parsec
+
+data SrcPos = Pos { line :: Int, column :: Int }
+    deriving (Eq, Ord, Data, Typeable)
+
+data SrcSpan = Span SrcPos SrcPos String | NoSpan String
+    deriving (Eq, Ord, Data, Typeable)
+
+data Located e = L SrcSpan e
+    deriving (Eq, Ord, Data, Typeable)
+
+none e = L (NoSpan (render $ pretty e)) e
+noneNoDocs = L (NoSpan "")
+
+at start end e = L (Span (Pos (Parsec.sourceLine start) (Parsec.sourceColumn start))
+                         (Pos (Parsec.sourceLine end  ) (Parsec.sourceColumn end  ))
+                         (render $ pretty e)) e
+
+merge (L s1 _) (L s2 _) e = L (span (render $ pretty e)) e
+    where span = case (s1,s2) of
+                   (Span start _ _, Span _ end _) -> Span start end
+                   (Span start end _, _) -> Span start end
+                   (_, Span start end _) -> Span start end
+                   (_, _) -> NoSpan
+
+mergeOldDocs (L s1 _) (L s2 _) e = L span e
+    where span = case (s1,s2) of
+                   (Span start _ d1, Span _ end d2) -> Span start end (d1 ++ "\n\n" ++ d2)
+                   (Span _ _ _, _) -> s1
+                   (_, Span _ _ _) -> s2
+                   (_, _) -> NoSpan ""
+
+sameAs (L s _) = L s
+
+
+instance Show SrcPos where
+    show (Pos r c) = show r ++ "," ++ show c
+
+instance Show SrcSpan where
+  show span = 
+      case span of
+        NoSpan _ -> ""
+        Span start end _ ->
+            case line start == line end of
+              False -> "between lines " ++ show (line start) ++ " and " ++ show (line end)
+              True -> "on line " ++ show (line end) ++ ", column " ++
+                      show (column start) ++ " to " ++ show (column end)
+
+instance Show e => Show (Located e) where
+  show (L s e) = "L (" ++ show s ++ ") (" ++ show e ++ ")"
+
+instance Pretty a => Pretty (Located a) where
+  pretty (L _ e) = pretty e
+
diff --git a/compiler/SourceSyntax/Module.hs b/compiler/SourceSyntax/Module.hs
new file mode 100644
--- /dev/null
+++ b/compiler/SourceSyntax/Module.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module SourceSyntax.Module where
+
+import Data.Data
+import Data.Binary
+import Data.List (intercalate)
+import qualified Data.Map as Map
+import Control.Applicative ((<$>), (<*>))
+import Control.Arrow (second)
+
+import SourceSyntax.Expression (LExpr)
+import SourceSyntax.Declaration
+import SourceSyntax.Type
+import System.FilePath (joinPath)
+import qualified Type.Type as Type
+
+data Module tipe var =
+    Module [String] Exports Imports [Declaration tipe var]
+    deriving (Show)
+
+type Exports = [String]
+
+type Imports = [(String, ImportMethod)]
+data ImportMethod = As String | Importing [String] | Hiding [String]
+                    deriving (Eq, Ord, Show, Data, Typeable)
+
+data MetadataModule t v = MetadataModule {
+    names     :: [String],
+    path      :: FilePath,
+    exports   :: [String],
+    imports   :: [(String, ImportMethod)],
+    program   :: LExpr t v,
+    types     :: Map.Map String Type.Variable,
+    fixities  :: [(Assoc, Int, String)],
+    aliases   :: [(String, [String], Type)],
+    datatypes :: [ (String, [String], [(String,[Type])]) ],
+    foreignImports :: [(String, LExpr t v, String, Type)],
+    foreignExports :: [(String, String, Type)]
+}
+
+type Interfaces = Map.Map String ModuleInterface
+type ADT = (String, [String], [(String,[Type])])
+
+data ModuleInterface = ModuleInterface {
+    iTypes   :: Map.Map String Type,
+    iAdts    :: [ADT],
+    iAliases :: [(String, [String], Type)]
+} deriving Show
+
+instance Binary ModuleInterface where
+  put modul = put (iTypes modul) >> put (iAdts modul) >> put (iAliases modul)
+  get = ModuleInterface <$> get <*> get <*> get
diff --git a/compiler/SourceSyntax/Pattern.hs b/compiler/SourceSyntax/Pattern.hs
new file mode 100644
--- /dev/null
+++ b/compiler/SourceSyntax/Pattern.hs
@@ -0,0 +1,48 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module SourceSyntax.Pattern where
+
+import Data.List (intercalate)
+import Data.Data
+import SourceSyntax.Helpers as Help
+import SourceSyntax.PrettyPrint
+import Text.PrettyPrint as PP
+import SourceSyntax.Literal as Literal
+
+data Pattern = PData String [Pattern]
+             | PRecord [String]
+             | PAlias String Pattern
+             | PVar String
+             | PAnything
+             | PLiteral Literal.Literal
+               deriving (Eq, Ord, Data, Typeable, Show)
+
+cons h t = PData "::" [h,t]
+nil      = PData "[]" []
+list     = foldr cons nil
+tuple es = PData ("_Tuple" ++ show (length es)) es
+
+
+instance Pretty Pattern where
+  pretty pattern =
+   case pattern of
+     PVar x -> variable x
+     PLiteral lit -> pretty lit
+     PRecord fs -> PP.braces (commaCat $ map PP.text fs)
+     PAlias x p -> prettyParens p <+> PP.text "as" <+> PP.text x
+     PAnything -> PP.text "_"
+     PData "::" [hd,tl] -> parensIf isCons (pretty hd) <+> PP.text "::" <+> pretty tl
+       where isCons = case hd of
+                        PData "::" _ -> True
+                        _ -> False
+     PData name ps ->
+        if isTuple name then
+            PP.parens . commaCat $ map pretty ps
+        else sep (PP.text name : map prettyParens ps)
+
+prettyParens pattern = parensIf needsThem (pretty pattern)
+  where
+    needsThem =
+      case pattern of
+        PData name (_:_) | not (isTuple name) -> True
+        PAlias _ _ -> True
+        _ -> False
diff --git a/compiler/SourceSyntax/PrettyPrint.hs b/compiler/SourceSyntax/PrettyPrint.hs
new file mode 100644
--- /dev/null
+++ b/compiler/SourceSyntax/PrettyPrint.hs
@@ -0,0 +1,18 @@
+
+module SourceSyntax.PrettyPrint where
+
+import Text.PrettyPrint
+import qualified SourceSyntax.Helpers as Help
+
+class Pretty a where
+  pretty :: a -> Doc
+
+instance Pretty () where
+  pretty () = empty
+
+commaCat docs = cat (punctuate comma docs)
+commaSep docs = sep (punctuate comma docs)
+
+parensIf bool doc = if bool then parens doc else doc
+
+variable x = parensIf (Help.isOp x) (text x)
diff --git a/compiler/SourceSyntax/Type.hs b/compiler/SourceSyntax/Type.hs
new file mode 100644
--- /dev/null
+++ b/compiler/SourceSyntax/Type.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module SourceSyntax.Type where
+
+import Data.Binary
+import Data.Data
+import qualified Data.Map as Map
+import qualified SourceSyntax.Helpers as Help
+import Control.Applicative ((<$>), (<*>))
+import SourceSyntax.PrettyPrint
+import Text.PrettyPrint as P
+
+data Type = Lambda Type Type
+          | Var String
+          | Data String [Type]
+          | EmptyRecord
+          | Record [(String,Type)] Type
+            deriving (Eq, Show, Data, Typeable)
+
+fieldMap :: [(String,a)] -> Map.Map String [a]
+fieldMap fields =
+    foldl (\r (x,t) -> Map.insertWith (++) x [t] r) Map.empty fields
+
+recordOf :: [(String,Type)] -> Type
+recordOf fields = Record fields EmptyRecord
+
+listOf :: Type -> Type
+listOf t = Data "_List" [t]
+
+tupleOf :: [Type] -> Type
+tupleOf ts = Data ("_Tuple" ++ show (length ts)) ts
+
+
+instance Pretty Type where
+  pretty tipe =
+    case tipe of
+      Lambda t1 t2 -> P.sep [ t, P.sep (map (P.text "->" <+>) ts) ]
+        where t:ts = collectLambdas tipe
+      Var x -> P.text x
+      Data "_List" [t] -> P.brackets (pretty t)
+      Data name tipes
+          | Help.isTuple name -> P.parens . P.sep . P.punctuate P.comma $ map pretty tipes
+          | otherwise -> P.hang (P.text name) 2 (P.sep $ map prettyParens tipes)
+      EmptyRecord -> P.braces P.empty
+      Record fields ext -> P.braces $ P.hang (pretty ext <+> P.text "|") 4 prettyFields
+          where
+            prettyField (f,t) = P.text f <+> P.text ":" <+> pretty t
+            prettyFields = commaSep . map prettyField $ fields
+
+collectLambdas tipe =
+  case tipe of
+    Lambda arg@(Lambda _ _) body -> P.parens (pretty arg) : collectLambdas body
+    Lambda arg body -> pretty arg : collectLambdas body
+    _ -> [pretty tipe]
+
+prettyParens tipe = parensIf needed (pretty tipe)
+  where
+    needed =
+      case tipe of
+        Lambda _ _ -> True
+        Data _ [] -> False
+        Data _ _ -> True
+        _ -> False
+
+instance Binary Type where
+  put tipe =
+      case tipe of
+        Lambda t1 t2 ->
+            putWord8 0 >> put t1 >> put t2
+        Var x ->
+            putWord8 1 >> put x
+        Data ctor tipes ->
+            putWord8 2 >> put ctor >> put tipes
+        EmptyRecord ->
+            putWord8 3
+        Record fs ext ->
+            putWord8 4 >> put fs >> put ext
+
+  get = do
+      n <- getWord8
+      case n of
+        0 -> Lambda <$> get <*> get
+        1 -> Var <$> get
+        2 -> Data <$> get <*> get
+        3 -> return EmptyRecord
+        4 -> Record <$> get <*> get
diff --git a/compiler/Transform/Canonicalize.hs b/compiler/Transform/Canonicalize.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Transform/Canonicalize.hs
@@ -0,0 +1,178 @@
+module Transform.Canonicalize (interface, metadataModule) where
+
+import Control.Arrow ((***))
+import Control.Monad.Identity
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import qualified Data.List as List
+import qualified Data.Either as Either
+import SourceSyntax.Module
+import SourceSyntax.Expression
+import SourceSyntax.Location as Loc
+import SourceSyntax.Pattern
+import SourceSyntax.Helpers (isOp)
+import qualified SourceSyntax.Type as Type
+import qualified Transform.SortDefinitions as SD
+import Text.PrettyPrint as P
+
+
+interface :: String -> ModuleInterface -> ModuleInterface
+interface moduleName iface =
+    ModuleInterface {
+      iTypes = Map.mapKeys prefix (Map.map renameType' (iTypes iface)),
+      iAdts = map (both prefix renameCtors) (iAdts iface),
+      iAliases = map (both prefix renameType') (iAliases iface)
+    }
+  where
+    both f g (a,b,c) = (f a, b, g c)
+    prefix name = moduleName ++ "." ++ name
+
+    pair name = (name, moduleName ++ "." ++ name)
+    canon (name,_,_) = pair name
+    canons = Map.fromList $ concat
+             [ map canon (iAdts iface), map canon (iAliases iface) ]
+
+    renameCtors ctors =
+        map (prefix *** map renameType') ctors
+    renameType' =
+        runIdentity . renameType (\name -> return $ Map.findWithDefault name name canons)
+
+renameType :: (Monad m) => (String -> m String) -> Type.Type -> m Type.Type
+renameType rename tipe =
+    let rnm = renameType rename in
+    case tipe of
+      Type.Lambda a b -> Type.Lambda `liftM` rnm a `ap` rnm b
+      Type.Var x -> return tipe
+      Type.Data name ts -> Type.Data `liftM` rename name `ap` mapM rnm ts
+      Type.EmptyRecord -> return tipe
+      Type.Record fields ext -> Type.Record `liftM` mapM rnm' fields `ap` rnm ext
+          where rnm' (f,t) = (,) f `liftM` rnm t
+
+metadataModule :: Interfaces -> MetadataModule t v -> Either [Doc] (MetadataModule t v)
+metadataModule ifaces modul =
+  do _ <- case filter (\m -> Map.notMember m ifaces) (map fst realImports) of
+            [] -> Right ()
+            missings -> Left [ P.text $ "The following imports were not found: " ++ List.intercalate ", " missings ]
+     program' <- rename initialEnv (program modul)
+     aliases' <- mapM (third renameType') (aliases modul)
+     datatypes' <- mapM (third (mapM (second (mapM renameType')))) (datatypes modul)
+     return $ modul { program = program', aliases = aliases', datatypes = datatypes' }
+  where
+    second f (a,b) = (,) a `fmap` f b
+    third f (a,b,c) = (,,) a b `fmap` f c
+    renameType' =
+        Either.either (\err -> Left [P.text err]) return . renameType (replace "type" initialEnv)
+
+    get1 (a,_,_) = a
+    canon (name, importMethod) =
+        let pair pre var = (pre ++ drop (length name + 1) var, var)
+            iface = ifaces Map.! name
+            allNames = concat [ Map.keys (iTypes iface)
+                              , map get1 (iAliases iface)
+                              , concat [ n : map fst ctors | (n,_,ctors) <- iAdts iface ] ]
+        in  case importMethod of
+              As alias -> map (pair (alias ++ ".")) allNames
+              Hiding vars -> map (pair "") $ filter (flip Set.notMember vs) allNames
+                  where vs = Set.fromList vars
+              Importing vars -> map (pair "") $ filter (flip Set.member vs) allNames
+                  where vs = Set.fromList $ map (\v -> name ++ "." ++ v) vars
+
+    pair n = (n,n)
+    localEnv = map pair (map get1 (aliases modul) ++ map get1 (datatypes modul))
+    globalEnv = map pair $ ["_List",saveEnvName,"::","[]","Int","Float","Char","Bool"] ++
+                           map (\n -> "_Tuple" ++ show n) [0..9]
+    realImports = filter (not . List.isPrefixOf "Native." . fst) (imports modul)
+    initialEnv = Map.fromList (concatMap canon realImports ++ localEnv ++ globalEnv)
+
+
+type Env = Map.Map String String
+
+extend :: Env -> Pattern -> Env
+extend env pattern = Map.union (Map.fromList (zip xs xs)) env
+    where xs = Set.toList (SD.boundVars pattern)
+
+
+replace :: String -> Env -> String -> Either String String
+replace variable env v =
+    if List.isPrefixOf "Native." v then return v else
+    case Map.lookup v env of
+      Just v' -> return v'
+      Nothing -> Left $ "Could not find " ++ variable ++ " '" ++ v ++ "'." ++ msg
+          where
+            matches = filter (List.isInfixOf v) (Map.keys env)
+            msg = if null matches then "" else
+                      "\nClose matches include: " ++ List.intercalate ", " matches
+
+rename :: Env -> LExpr t v -> Either [Doc] (LExpr t v)
+rename env lexpr@(L s expr) =
+    let rnm = rename env
+        throw err = Left [ P.text $ "Error " ++ show s ++ "\n" ++ err ]
+        format = Either.either throw return
+    in
+    L s `liftM`
+    case expr of
+      Literal lit -> return expr
+
+      Range e1 e2 -> Range `liftM` rnm e1 `ap` rnm e2
+
+      Access e x -> Access `liftM` rnm e `ap` return x
+
+      Remove e x -> flip Remove x `liftM` rnm e
+
+      Insert e x v -> flip Insert x `liftM` rnm e `ap` rnm v
+
+      Modify e fs ->
+          Modify `liftM` rnm e `ap` mapM (\(x,e) -> (,) x `liftM` rnm e) fs
+
+      Record fs -> Record `liftM` mapM frnm fs
+          where
+            frnm (f,e) = (,) f `liftM` rename env e
+
+      Binop op e1 e2 ->
+          do op' <- format (replace "variable" env op)
+             Binop op' `liftM` rnm e1 `ap` rnm e2
+
+      Lambda pattern e ->
+          let env' = extend env pattern in
+          Lambda pattern `liftM` rename env' e
+
+      App e1 e2 -> App `liftM` rnm e1 `ap` rnm e2
+
+      MultiIf ps -> MultiIf `liftM` mapM grnm ps
+              where grnm (b,e) = (,) `liftM` rnm b `ap` rnm e
+
+      Let defs e -> Let `liftM` mapM rename' defs `ap` rename env' e
+          where
+            env' = foldl extend env [ pattern | Def pattern _ <- defs ]
+            rename' def =
+                case def of
+                  Def p exp ->
+                      Def `liftM` format (renamePattern env' p) `ap` rename env' exp
+                  TypeAnnotation name tipe ->
+                      TypeAnnotation name `liftM`
+                          renameType (format . replace "variable" env') tipe
+
+      Var x -> Var `liftM` format (replace "variable" env x)
+
+      Data name es -> Data name `liftM` mapM rnm es
+
+      ExplicitList es -> ExplicitList `liftM` mapM rnm es
+
+      Case e cases -> Case `liftM` rnm e `ap` mapM branch cases
+          where
+            branch (pattern,e) = (,) `liftM` format (renamePattern env pattern)
+                                        `ap` rename (extend env pattern) e
+
+      Markdown _ -> return expr
+
+
+renamePattern :: Env -> Pattern -> Either String Pattern
+renamePattern env pattern =
+    case pattern of
+      PVar _ -> return pattern
+      PLiteral _ -> return pattern
+      PRecord _ -> return pattern
+      PAnything -> return pattern
+      PAlias x p -> PAlias x `liftM` renamePattern env p
+      PData name ps -> PData `liftM` replace "pattern" env name
+                                `ap` mapM (renamePattern env) ps
diff --git a/compiler/Transform/Check.hs b/compiler/Transform/Check.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Transform/Check.hs
@@ -0,0 +1,63 @@
+module Transform.Check (mistakes) where
+
+import Transform.SortDefinitions (boundVars)
+import SourceSyntax.Everything
+import qualified SourceSyntax.Type as T
+import Data.List as List
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import Data.Data
+import Data.Generics.Uniplate.Data
+import Text.PrettyPrint as P
+
+
+mistakes :: (Data t, Data v) => [Declaration t v] -> [Doc]
+mistakes decls =
+    map P.text $ concatMap findErrors (getLets decls)
+  where
+    findErrors defs = duplicates defs ++ badOrder defs
+
+
+getLets :: (Data t, Data v) => [Declaration t v] -> [[Def t v]]
+getLets decls = defs : concatMap getSubLets defs
+    where
+      defs = concatMap (\d -> case d of Definition d -> [d] ; _ -> []) decls
+
+      getSubLets def =
+          case def of
+            Def pattern expr -> [ defs | Let defs _ <- universeBi expr ]
+            TypeAnnotation _ _ -> []
+
+
+duplicates :: [Def t v] -> [String]
+duplicates defs =
+    map defMsg (dups definitions) ++ map annMsg (dups annotations)
+  where
+    annotations = List.sort [ name | TypeAnnotation name _ <- defs ]
+    definitions = List.sort $ concatMap Set.toList [ boundVars pattern | Def pattern _ <- defs ]
+
+    dups = map head . filter ((>1) . length) . List.group
+
+    msg = "Syntax Error: There can only be one "
+    defMsg x = msg ++ "definition of '" ++ x ++ "'."
+    annMsg x = msg ++ "type annotation for '" ++ x ++ "'."
+
+
+badOrder :: [Def t v] -> [String]
+badOrder defs = go defs
+    where
+      msg x = "Syntax Error: The type annotation for '" ++ x ++
+              "' must be directly above its definition."
+
+      go defs =
+          case defs of
+            TypeAnnotation name _ : Def (PVar name') _ : rest
+                | name == name' -> go rest
+
+            TypeAnnotation name _  : rest -> [msg name] ++ go rest
+
+            _ : rest -> go rest
+
+            _ -> []
+
+
diff --git a/compiler/Transform/Optimize.hs b/compiler/Transform/Optimize.hs
--- a/compiler/Transform/Optimize.hs
+++ b/compiler/Transform/Optimize.hs
@@ -1,10 +1,8 @@
-module Optimize (optimize) where
+module Transform.Optimize (optimize) where
 
-import Ast
-import Context
-import Control.Arrow (second)
+import SourceSyntax.Everything
+import Control.Arrow (second, (***))
 import Data.Char (isAlpha)
-import Substitute
 
 optimize (Module name ims exs stmts) =
     Module name ims exs (map optimizeStmt stmts)
@@ -15,122 +13,120 @@
 class Simplify a where
   simp :: a -> a
 
-instance Simplify Statement where
+instance Simplify (Declaration t v) 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 (Def t v) where
+  simp (Def name e) = Def name (simp e)
+  simp x = x
 
-instance Simplify e => Simplify (Context e) where
-  simp (C t s e) = C t s (simp e)
+instance Simplify e => Simplify (Located e) where
+  simp (L s e) = L s (simp e)
 
-instance Simplify Expr where
+instance Simplify (Expr t v) where
   simp expr =
     let f = simp in
     case expr of
       Range e1 e2 -> Range (f e1) (f e2)
-      Binop op e1 e2 -> simp_binop op (f e1) (f e2)
+      Binop op e1 e2 -> binop op (f e1) (f e2)
       Lambda x e -> Lambda x (f e)
-      Record fs -> Record (map (\(f,as,e) -> (f, as, simp e)) fs)
-      App (C t s (Lambda x e1)) e2 -> 
-        if isValue e2' then subst x e2' e1' else App (C t s (Lambda x ce1')) ce2'
-              where ce1'@(C _ _ e1') = f e1
-                    ce2'@(C _ _ e2') = f e2
+      Record fs -> Record (map (second simp) fs)
       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 simp defs) (f e)
       Data name es -> Data name (map f es)
+      MultiIf es -> MultiIf . clipBranches $ map (f *** f) es
       Case e cases -> Case (f e) (map (second f) cases)
       _ -> expr
 
-simp_if (C _ _ (Boolean b)) (C _ _ e2) (C _ _ e3) = if b then e2 else e3
-simp_if a b c = If a b c
 
+clipBranches [] = []
+clipBranches (e:es) =
+    case e of
+      (L _ (Literal (Boolean True)), _) -> [e]
+      _ -> e : clipBranches es
+
+
 isValue e =
-    case e of { IntNum _  -> True
-              ; FloatNum _ -> True
-              ; Chr _ -> True
-              ; Str _ -> True
-              ; Boolean _ -> True
-              ; Var _ -> True
-              ; Data _ _ -> True
-              ; _ -> False }
+    case e of
+      Literal _  -> True
+      Var _      -> True
+      Data _ _   -> True
+      _          -> False
 
-simp_binop = binop
 
-binop op ce1@(C t1 s1 e1) ce2@(C t2 s2 e2) =
-  let c1 = C t1 s1 in
-  let c2 = C t2 s2 in
+binop op ce1@(L s1 e1) ce2@(L s2 e2) =
+  let c1 = L s1
+      c2 = L s2
+      int = Literal . IntNum
+      str = Literal . Str
+      bool = Literal . Boolean
+  in  
   case (op, e1, e2) of
-    (_, IntNum n, IntNum m) -> case op of
-                                 { "+" -> IntNum $ (+) n m
-                                 ; "-" -> IntNum $ (-) n m
-                                 ; "*" -> IntNum $ (*) n m
-                                 ; "^" -> IntNum $ n ^ m
-                                 ; "div" -> IntNum $ div n m
-                                 ; "mod" -> IntNum $ mod n m
-                                 ; "<" -> Boolean $ n < m
-                                 ; ">" -> Boolean $ n < m
-                                 ; "<=" -> Boolean $ n <= m
-                                 ; ">=" -> Boolean $ n >= m
-                                 ; "==" -> Boolean $ n == m
-                                 ; "/=" -> Boolean $ n /= m
-                                 ;  _  -> Binop op ce1 ce2 }
-
+    (_, Literal (IntNum n), Literal (IntNum m)) ->
+        case op of
+          { "+" -> int $ (+) n m
+          ; "-" -> int $ (-) n m
+          ; "*" -> int $ (*) n m
+          ; "^" -> int $ n ^ m
+          ; "div" -> int $ div n m
+          ; "mod" -> int $ mod n m
+          ; "rem" -> int $ rem n m
+          ; "<" -> bool $ n < m
+          ; ">" -> bool $ n > m
+          ; "<=" -> bool $ n <= m
+          ; ">=" -> bool $ n >= m
+          ; "==" -> bool $ n == m
+          ; "/=" -> bool $ n /= m
+          ;  _  -> Binop op ce1 ce2 }
+  {--
     -- flip order to move lone integers to the left
     ("+", _, IntNum n) -> binop "+" ce2 ce1
     ("*", _, IntNum n) -> binop "*" ce2 ce1
 
     ("+", IntNum 0, _) -> e2
-    ("+", IntNum n, Binop "+" (C _ _ (IntNum m)) ce) ->
+    ("+", IntNum n, Binop "+" (L _ (IntNum m)) ce) ->
         binop "+" (c1 $ IntNum (n+m)) ce
-    ("+", Binop "+" (C _ _ (IntNum n)) ce1'
-        , Binop "+" (C _ _ (IntNum m)) ce2') ->
-        binop "+" (noContext $ IntNum (n+m)) (noContext $ Binop "+" ce1' ce2')
+    ("+", Binop "+" (L _ (IntNum n)) ce1'
+        , Binop "+" (L _ (IntNum m)) ce2') ->
+        binop "+" (none $ IntNum (n+m)) (none $ Binop "+" ce1' ce2')
 
     ("*", IntNum 0, _) -> e1
     ("*", IntNum 1, _) -> e2
-    ("*", IntNum n, Binop "*" (C _ _ (IntNum m)) ce) ->
-        binop "*" (noContext $ IntNum (n*m)) ce
-    ("*", Binop "*" (C _ _ (IntNum n)) ce1'
-        , Binop "*" (C _ _ (IntNum m)) ce2') ->
-        binop "*" (noContext $ IntNum (n*m)) (noContext $ Binop "*" ce1' ce2')
+    ("*", IntNum n, Binop "*" (L _ (IntNum m)) ce) ->
+        binop "*" (none $ IntNum (n*m)) ce
+    ("*", Binop "*" (L _ (IntNum n)) ce1'
+        , Binop "*" (L _ (IntNum m)) ce2') ->
+        binop "*" (none $ IntNum (n*m)) (none $ Binop "*" ce1' ce2')
 
     ("-", _, IntNum 0) -> e1
     ("/", _, IntNum 1) -> e1
     ("div", _, IntNum 1) -> e1
-
-    (_, Boolean n, Boolean m) -> case op of "&&" -> Boolean $ n && m
-                                            "||" -> Boolean $ n || m
-                                            _    -> Binop op ce1 ce2
-
-    ("&&", Boolean  True, _) -> e2
-    ("&&", Boolean False, _) -> Boolean False
-    ("||", Boolean  True, _) -> Boolean True
-    ("||", Boolean False, _) -> e2
+--}
+    (_, Literal (Boolean n), Literal (Boolean m)) ->
+        case op of
+          "&&" -> bool $ n && m
+          "||" -> bool $ n || m
+          _    -> Binop op ce1 ce2
 
-    ("::", _, _) -> let (C _ _ e) = cons ce1 ce2 in e
+    ("&&", Literal (Boolean  True), _) -> e2
+    ("&&", Literal (Boolean False), _) -> bool False
+    ("||", Literal (Boolean  True), _) -> bool True
+    ("||", Literal (Boolean False), _) -> e2
 
-    ("++", Str s1, Str s2) -> Str $ s1 ++ s2
-    ("++", Str s1, Binop "++" (C _ _ (Str s2)) ce) ->
-        Binop "++" (c1 $ Str $ s1 ++ s2) ce
-    ("++", Binop "++" e (C _ _ (Str s1)), Str s2) ->
-        Binop "++" e (c1 $ Str $ s1 ++ s2)
+    ("::", _, _) -> Data "::" [ce1, ce2]
 
-    ("++", Data "Nil" [], _) -> e2
-    ("++", _, Data "Nil" []) -> e1
-    ("++", Data "Cons" [h,t], _) -> Data "Cons" [h, noContext $ binop "++" t ce2]
+    ("++", Literal (Str s1), Literal (Str s2)) -> str $ s1 ++ s2
+    ("++", Literal (Str s1), Binop "++" (L _ (Literal (Str s2))) ce) ->
+        Binop "++" (c1 . str $ s1 ++ s2) ce
+    ("++", Binop "++" e (L _ (Literal (Str s1))), Literal (Str s2)) ->
+        Binop "++" e (c1 . str $ s1 ++ s2)
 
-    ("|>", _, _) -> App ce2 ce1
-    ("<|", _, _) -> App ce1 ce2
-    ("$", _, _) -> App ce1 ce2
-    (".", _, _) ->
-        Lambda "x" (noContext $
-                      App ce1 (noContext $ App ce2 (noContext $ Var "x")))
+    ("++", Data "[]" [], _) -> e2
+    ("++", _, Data "[]" []) -> e1
+    ("++", Data "::" [h,t], _) -> Data "::" [h, none $ binop "++" t ce2]
 
     _ | isAlpha (head op) || '_' == head op ->
-          App (noContext $ App (noContext $ Var op) ce1) ce2
+          App (none $ App (none $ Var op) ce1) ce2
       | otherwise -> Binop op ce1 ce2
diff --git a/compiler/Transform/Rename.hs b/compiler/Transform/Rename.hs
deleted file mode 100644
--- a/compiler/Transform/Rename.hs
+++ /dev/null
@@ -1,149 +0,0 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-module Rename (renameModule, derename, deprime) where
-
-import Ast
-import Context
-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 stmt =
-    case stmt of
-      Definition def -> Definition `liftM` rename env def
-      Datatype name args tcs ->
-          return $ Datatype name args $ map (first env) tcs
-      TypeAlias n xs t -> return (TypeAlias n xs t)
-      TypeAnnotation n t -> return (TypeAnnotation (env n) t)
-      ImportEvent js base elm tipe ->
-          do base' <- rename env base
-             return $ ImportEvent js base' (env elm) tipe
-      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 a => Rename (Context a) where
-  rename env (C t s e) = C t s `liftM` rename env e
-                          
-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
-
-      Remove e x -> flip Remove x `liftM` rnm e
-
-      Insert e x v -> flip Insert x `liftM` rnm e
-                                       `ap` rnm v
-
-      Modify e fs  -> Modify `liftM` rnm e
-                                `ap` mapM (\(x,e) -> (,) x `liftM` rnm e) fs
-
-      Record fs -> Record `liftM` mapM frnm fs
-          where frnm (f,as,e) = do env' <- extends env as
-                                   e' <- rename env' e
-                                   return (f, map env' as, e') 
-
-      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
-
-      MultiIf ps -> MultiIf `liftM` mapM grnm ps
-              where grnm (b,e) = (,) `liftM` rnm b
-                                        `ap` 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'')
-      PRecord fs ->
-          return (pattern, foldr (\f e n -> if n == f then f else env n) env fs)
-
-patternRename :: (String -> String) -> (Pattern, CExpr) -> GuidCounter (Pattern, CExpr)
-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/compiler/Transform/SortDefinitions.hs b/compiler/Transform/SortDefinitions.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Transform/SortDefinitions.hs
@@ -0,0 +1,198 @@
+
+module Transform.SortDefinitions (sortDefs, boundVars, flattenLets) where
+
+import Control.Monad.State
+import Control.Applicative ((<$>))
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import qualified SourceSyntax.Type as ST
+import SourceSyntax.Everything
+import qualified Data.Graph as Graph
+import qualified Data.Map as Map
+import qualified Data.Maybe as Maybe
+
+boundVars :: Pattern -> Set.Set String
+boundVars pattern =
+    case pattern of
+      PVar x -> Set.singleton x
+      PAlias x p -> Set.insert x (boundVars p)
+      PData _ ps -> Set.unions (map boundVars ps)
+      PRecord fields -> Set.fromList fields
+      PAnything -> Set.empty
+      PLiteral _ -> Set.empty
+
+ctors :: Pattern -> [String]
+ctors pattern =
+    case pattern of
+      PVar x -> []
+      PAlias x p -> ctors p
+      PData ctor ps -> ctor : concatMap ctors ps
+      PRecord fields -> []
+      PAnything -> []
+      PLiteral _ -> []
+
+free :: String -> State (Set.Set String) ()
+free x = modify (Set.insert x)
+
+bound :: Set.Set String -> State (Set.Set String) ()
+bound boundVars = modify (\freeVars -> Set.difference freeVars boundVars)
+
+sortDefs :: LExpr t v -> LExpr t v
+sortDefs expr = evalState (reorder expr) Set.empty
+
+flattenLets defs lexpr@(L _ expr) =
+    case expr of
+      Let ds body -> flattenLets (defs ++ ds) body
+      _ -> (defs, lexpr)
+
+
+reorder :: LExpr t v -> State (Set.Set String) (LExpr t v)
+reorder lexpr@(L s expr) =
+    L s `liftM`
+    case expr of
+      -- Be careful adding and restricting freeVars
+      Var x -> free x >> return expr
+
+      Lambda p e ->
+          uncurry Lambda `liftM` bindingReorder (p,e)
+
+      Binop op e1 e2 ->
+          do free op
+             Binop op `liftM` reorder e1 `ap` reorder e2
+
+      Case e cases ->
+          Case `liftM` reorder e `ap` mapM bindingReorder cases
+
+      Data name es ->
+          do free name
+             Data name `liftM` mapM reorder es
+
+      -- Just pipe the reorder though
+      Literal _ -> return expr
+
+      Range e1 e2 ->
+          Range `liftM` reorder e1 `ap` reorder e2
+
+      ExplicitList es ->
+          ExplicitList `liftM` mapM reorder es
+
+      App e1 e2 ->
+          App `liftM` reorder e1 `ap` reorder e2
+
+      MultiIf branches ->
+          MultiIf `liftM` mapM reorderPair branches
+
+      Access e lbl ->
+          Access `liftM` reorder e `ap` return lbl
+
+      Remove e lbl ->
+          Remove `liftM` reorder e `ap` return lbl
+
+      Insert e lbl v ->
+          Insert `liftM` reorder e `ap` return lbl `ap` reorder v
+
+      Modify e fields ->
+          Modify `liftM` reorder e `ap` mapM reorderField fields
+
+      Record fields ->
+          Record `liftM` mapM reorderField fields
+
+      Markdown _ -> return expr
+
+      -- Actually do some reordering
+      Let defs body ->
+          do body' <- reorder body
+
+             -- Sort defs into strongly connected components.This
+             -- allows the programmer to write definitions in whatever
+             -- order they please, we can still define things in order
+             -- and generalize polymorphic functions when appropriate.
+             sccs <- Graph.stronglyConnComp <$> buildDefDict defs
+             let defss = map Graph.flattenSCC sccs
+             
+             -- remove let-bound variables from the context
+             let getPatterns def =
+                     case def of
+                       Def pattern _ -> pattern
+                       TypeAnnotation name _ -> PVar name
+             forM (map getPatterns defs) $ \pattern -> do
+                bound (boundVars pattern)
+                mapM free (ctors pattern)
+
+             let addDefs ds bod = L s (Let (concatMap toDefs ds) bod)
+                     where
+                       toDefs (pattern, expr, Nothing) = [ Def pattern expr ]
+                       toDefs (PVar name, expr, Just tipe) =
+                           [ TypeAnnotation name tipe, Def (PVar name) expr ]
+             
+                 L _ let' = foldr addDefs body' defss
+
+             return let'
+
+
+reorderField (label, expr) =
+    (,) label `liftM` reorder expr
+
+reorderPair (e1,e2) =
+    (,) `liftM` reorder e1 `ap` reorder e2
+
+bindingReorder :: (Pattern, LExpr t v) -> State (Set.Set String) (Pattern, LExpr t v)
+bindingReorder (pattern,expr) =
+    do expr' <- reorder expr
+       bound (boundVars pattern)
+       mapM free (ctors pattern)
+       return (pattern, expr')
+
+
+type PDef t v = (Pattern, LExpr t v, Maybe ST.Type)
+
+reorderAndGetDependencies :: PDef t v -> State (Set.Set String) (PDef t v, [String])
+reorderAndGetDependencies (pattern, expr, mType) =
+    do globalFrees <- get
+       -- work in a fresh environment
+       put Set.empty
+       expr' <- reorder expr
+       localFrees <- get
+       -- merge with global frees
+       modify (Set.union globalFrees)
+       return ((pattern, expr', mType), Set.toList localFrees)
+
+
+-- This also reorders the all of the sub-expressions in the Def list.
+buildDefDict :: [Def t v] -> State (Set.Set String) [(PDef t v, Int, [Int])]
+buildDefDict defs =
+  do pdefsDeps <- mapM reorderAndGetDependencies (getPDefs defs)
+     return $ realDeps (addKey pdefsDeps)
+
+  where
+    getPDefs :: [Def t v] -> [PDef t v]
+    getPDefs defs = map (\(p,(e,t)) -> (p,e,t)) $
+                    Map.toList $ go defs Map.empty Map.empty
+      where
+        go [] ds ts =
+            Map.unions [ Map.difference ds ts
+                       , Map.intersectionWith (\(e,_) t -> (e,Just t)) ds ts ]
+        
+        go (def:defs) ds ts =
+            case def of
+              Def p e -> go defs (Map.insert p (e, Nothing) ds) ts
+              TypeAnnotation name tipe -> go defs ds (Map.insert (PVar name) tipe ts)
+
+    addKey :: [(PDef t v, [String])] -> [(PDef t v, Int, [String])]
+    addKey = zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
+
+    variableToKey :: (PDef t v, Int, [String]) -> [(String, Int)]
+    variableToKey ((pattern, _, _), key, _) =
+        [ (var, key) | var <- Set.toList (boundVars pattern) ]
+
+    variableToKeyMap :: [(PDef t v, Int, [String])] -> Map.Map String Int
+    variableToKeyMap pdefsDeps =
+        Map.fromList (concatMap variableToKey pdefsDeps)
+
+    realDeps :: [(PDef t v, Int, [String])] -> [(PDef t v, Int, [Int])]
+    realDeps pdefsDeps = map convert pdefsDeps
+        where
+          varDict = variableToKeyMap pdefsDeps
+          convert (pdef, key, deps) =
+              (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)
+
diff --git a/compiler/Transform/Substitute.hs b/compiler/Transform/Substitute.hs
--- a/compiler/Transform/Substitute.hs
+++ b/compiler/Transform/Substitute.hs
@@ -1,28 +1,30 @@
-module Substitute (subst) where
+{-# OPTIONS_GHC -Wall #-}
+module Transform.Substitute (subst) where
 
-import Ast
-import Context
+import SourceSyntax.Expression
+import SourceSyntax.Location
 import Control.Arrow (second, (***))
 
-subst :: String -> Expr -> Expr -> Expr
+subst :: String -> Expr t v -> Expr t v -> Expr t v
 subst old new expr =
-    let f (C t s e) = C t s (subst old new e) in
+    let f (L s e) = L s (subst old new e) in
     case expr of
       Range e1 e2 -> Range (f e1) (f e2)
-      Access e x -> Access (f e) x
-      Remove e x -> Remove (f e) x
-      Insert e x v -> Insert (f e) x (f v)
-      Modify r fs -> Modify (f r) (map (second f) fs)
-      Record fs -> Record (map (\(lbl,as,e) -> (lbl,as,f e)) fs)
+      ExplicitList es -> ExplicitList (map f es)
       Binop op e1 e2 -> Binop op (f e1) (f e2)
-      Lambda x e -> if x == old then expr else Lambda x (f e)
+      Lambda p e -> Lambda p (f e)
       App e1 e2 -> App (f e1) (f e2)
-      If e1 e2 e3 -> If (f e1) (f e2) (f e3)
       MultiIf ps -> MultiIf (map (f *** f) ps)
-      Let defs e -> Let (map substDef defs) (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)
+      Let defs body -> Let (map substDef defs) (f body)
+              where substDef (Def name e)  = Def name (f e)
+                    substDef anno@(TypeAnnotation _ _) = anno
       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)
-      _ -> expr
+      Access e x -> Access (f e) x
+      Remove e x -> Remove (f e) x
+      Insert e x v -> Insert (f e) x (f v)
+      Modify r fs -> Modify (f r) (map (second f) fs)
+      Record fs -> Record (map (second f) fs)
+      Literal _ -> expr
+      Markdown _ -> expr
diff --git a/compiler/Type/Constrain/Declaration.hs b/compiler/Type/Constrain/Declaration.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/Constrain/Declaration.hs
@@ -0,0 +1,68 @@
+module Type.Constrain.Declaration where
+
+import Control.Monad
+import Control.Applicative ((<$>))
+
+import qualified Data.Map as Map
+
+import qualified Type.Constrain.Expression as TcExpr
+import qualified Type.Environment as Env
+
+import SourceSyntax.Declaration
+import qualified SourceSyntax.Everything as Src
+import qualified SourceSyntax.Type as Type
+
+toExpr :: [Declaration t v] -> [Src.Def t v]
+toExpr = concatMap toDefs
+
+toDefs :: Declaration t v -> [Src.Def t v]
+toDefs decl =
+  case decl of
+    Definition def -> [def]
+
+    Datatype name tvars constructors -> concatMap toDefs constructors
+      where
+        toDefs (ctor, tipes) =
+            let vars = take (length tipes) arguments
+                tbody = Type.Data name $ map Type.Var tvars
+                body = Src.none . Src.Data ctor $ map (Src.none . Src.Var) vars
+            in  [ Src.TypeAnnotation ctor $ foldr Type.Lambda tbody tipes
+                , Src.Def (Src.PVar ctor) $ buildFunction body vars
+                ]
+
+    TypeAlias name tvars tipe@(Type.Record fields ext) ->
+        [ Src.TypeAnnotation name $ foldr Type.Lambda tipe args
+        , Src.Def (Src.PVar name) $ buildFunction record vars ]
+      where
+        args = case ext of
+                 Type.EmptyRecord -> map snd fields
+                 _ -> map snd fields ++ [ext]
+
+        var = Src.none . Src.Var
+        vars = take (length args) arguments
+
+        efields = zip (map fst fields) (map var vars)
+        record = case ext of
+                   Type.EmptyRecord -> Src.none $ Src.Record efields
+                   _ -> foldl (\r (f,v) -> Src.none $ Src.Insert r f v) (var $ last vars) efields
+
+    -- Type aliases must be added to an extended equality dictionary,
+    -- but they do not require any basic constraints.
+    TypeAlias _ _ _ -> []
+
+    ImportEvent _ expr@(Src.L s _) name tipe ->
+        [ Src.TypeAnnotation name tipe
+        , Src.Def (Src.PVar name) (Src.L s $ Src.App (Src.L s $ Src.Var "constant") expr) ]
+
+    ExportEvent _ name tipe ->
+        [ Src.TypeAnnotation name tipe ]
+
+    -- no constraints are needed for fixity declarations
+    Fixity _ _ _ -> []
+
+
+arguments :: [String]
+arguments = map (:[]) ['a'..'z'] ++ map (\n -> "_" ++ show n) [1..]
+
+buildFunction body@(Src.L s _) vars =
+    foldr (\p e -> Src.L s (Src.Lambda p e)) body (map Src.PVar vars)
diff --git a/compiler/Type/Constrain/Expression.hs b/compiler/Type/Constrain/Expression.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/Constrain/Expression.hs
@@ -0,0 +1,223 @@
+module Type.Constrain.Expression where
+
+import qualified Data.List as List
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import Control.Arrow (second)
+import Control.Applicative ((<$>),(<*>))
+import qualified Control.Monad as Monad
+import Control.Monad.Error (ErrorT, runErrorT)
+import Control.Monad.State
+import Data.Traversable (traverse)
+
+import SourceSyntax.Location as Loc
+import SourceSyntax.Pattern (Pattern(PVar))
+import SourceSyntax.Expression
+import qualified SourceSyntax.Type as SrcT
+import Type.Type hiding (Descriptor(..))
+import Type.Fragment
+import qualified Type.Environment as Env
+import qualified Type.Constrain.Literal as Literal
+import qualified Type.Constrain.Pattern as Pattern
+import qualified Transform.SortDefinitions as SD
+
+
+constrain :: Env.Environment -> LExpr a b -> Type -> IO TypeConstraint
+constrain env (L span expr) tipe =
+    let list t = Env.get env Env.types "_List" <| t
+        and = L span . CAnd
+        true = L span CTrue
+        t1 === t2 = L span (CEqual t1 t2)
+        x <? t = L span (CInstance x t)
+        clet schemes c = L span (CLet schemes c)
+    in
+    case expr of
+      Literal lit -> Literal.constrain env span lit tipe
+
+      Var name -> return (name <? tipe)
+
+      Range lo hi ->
+          exists $ \x -> do
+            clo <- constrain env lo x
+            chi <- constrain env hi x
+            return $ and [clo, chi, list x === tipe]
+
+      ExplicitList exprs ->
+          exists $ \x -> do
+            cs <- mapM (\e -> constrain env e x) exprs
+            return . and $ list x === tipe : cs
+
+      Binop op e1 e2 ->
+          exists $ \t1 ->
+          exists $ \t2 -> do
+            c1 <- constrain env e1 t1
+            c2 <- constrain env e2 t2
+            return $ and [ c1, c2, op <? (t1 ==> t2 ==> tipe) ]
+
+      Lambda p e ->
+          exists $ \t1 ->
+          exists $ \t2 -> do
+            fragment <- try span $ Pattern.constrain env p t1
+            c2 <- constrain env e t2
+            let c = ex (vars fragment) (clet [monoscheme (typeEnv fragment)]
+                                             (typeConstraint fragment /\ c2 ))
+            return $ c /\ tipe === (t1 ==> t2)
+
+      App e1 e2 ->
+          exists $ \t -> do
+            c1 <- constrain env e1 (t ==> tipe)
+            c2 <- constrain env e2 t
+            return $ c1 /\ c2
+
+      MultiIf branches -> and <$> mapM constrain' branches
+          where 
+             bool = Env.get env Env.types "Bool"
+             constrain' (b,e) = do
+                  cb <- constrain env b bool
+                  ce <- constrain env e tipe
+                  return (cb /\ ce)
+
+      Case exp branches ->
+          exists $ \t -> do
+            ce <- constrain env exp t
+            let branch (p,e) = do
+                  fragment <- try span $ Pattern.constrain env p t
+                  clet [toScheme fragment] <$> constrain env e tipe
+            and . (:) ce <$> mapM branch branches
+
+      Data name exprs ->
+          do pairs <- mapM pair exprs
+             (ctipe, cs) <- Monad.foldM step (tipe,true) (reverse pairs)
+             return (cs /\ name <? ctipe)
+          where
+            pair e = do v <- var Flexible -- needs an ex
+                        return (e, VarN v)
+
+            step (t,c) (e,x) = do
+                c' <- constrain env e x
+                return (x ==> t, c /\ c')
+
+      Access e label ->
+          exists $ \t ->
+              constrain env e (record (Map.singleton label [tipe]) t)
+
+      Remove e label ->
+          exists $ \t ->
+              constrain env e (record (Map.singleton label [t]) tipe)
+
+      Insert e label value ->
+          exists $ \tVal ->
+          exists $ \tRec -> do
+              cVal <- constrain env value tVal
+              cRec <- constrain env e tRec
+              let c = tipe === record (Map.singleton label [tVal]) tRec
+              return (and [cVal, cRec, c])
+
+      Modify e fields ->
+          exists $ \t -> do
+              oldVars <- forM fields $ \_ -> var Flexible
+              let oldFields = SrcT.fieldMap (zip (map fst fields) (map VarN oldVars))
+              cOld <- ex oldVars <$> constrain env e (record oldFields t)
+
+              newVars <- forM fields $ \_ -> var Flexible
+              let newFields = SrcT.fieldMap (zip (map fst fields) (map VarN newVars))
+              let cNew = tipe === record newFields t
+
+              cs <- zipWithM (constrain env) (map snd fields) (map VarN newVars)
+
+              return $ cOld /\ ex newVars (and (cNew : cs))
+
+      Record fields ->
+          do vars <- forM fields $ \_ -> var Flexible
+             cs <- zipWithM (constrain env) (map snd fields) (map VarN vars)
+             let fields' = SrcT.fieldMap (zip (map fst fields) (map VarN vars))
+                 recordType = record fields' (TermN EmptyRecord1)
+             return . ex vars . and $ tipe === recordType : cs
+
+      Markdown _ ->
+          return ("Graphics.Element.markdown" <? tipe)
+
+      Let defs body ->
+          do c <- case body of
+                    L _ (Var name) | name == saveEnvName -> return (L span CSaveEnv)
+                    _ -> constrain env body tipe
+             (schemes, rqs, fqs, header, c2, c1) <-
+                 Monad.foldM (constrainDef env)
+                             ([], [], [], Map.empty, true, true)
+                             (collapseDefs defs)
+             return $ clet schemes
+                           (clet [Scheme rqs fqs (clet [monoscheme header] c2) header ]
+                                 (c1 /\ c))
+
+constrainDef env info (pattern, expr, maybeTipe) =
+    let qs = [] -- should come from the def, but I'm not sure what would live there...
+        (schemes, rigidQuantifiers, flexibleQuantifiers, headers, c2, c1) = info
+    in
+    case (pattern, maybeTipe) of
+      (PVar name, Just tipe) ->
+          do flexiVars <- mapM (\_ -> var Flexible) qs
+             let inserts = zipWith (\arg typ -> Map.insert arg (VarN typ)) qs flexiVars
+                 env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
+             (vars, typ) <- Env.instantiateType env tipe Map.empty
+             let scheme = Scheme { rigidQuantifiers = [],
+                                   flexibleQuantifiers = flexiVars ++ vars,
+                                   constraint = Loc.noneNoDocs CTrue,
+                                   header = Map.singleton name typ }
+             c <- constrain env' expr typ
+             return ( scheme : schemes
+                    , rigidQuantifiers
+                    , flexibleQuantifiers
+                    , headers
+                    , c2
+                    , fl rigidQuantifiers c /\ c1 )
+
+      (PVar name, Nothing) ->
+          do v <- var Flexible
+             rigidVars <- mapM (\_ -> var Rigid) qs -- Some mistake may be happening here.
+                                                    -- Currently, qs is always the empty list.
+             let tipe = VarN v
+                 inserts = zipWith (\arg typ -> Map.insert arg (VarN typ)) qs rigidVars
+                 env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
+             c <- constrain env' expr tipe
+             return ( schemes
+                    , rigidVars ++ rigidQuantifiers
+                    , v : flexibleQuantifiers
+                    , Map.insert name tipe headers
+                    , c /\ c2
+                    , c1 )
+
+
+expandPattern :: (Pattern, LExpr t v, Maybe SrcT.Type)
+              -> [(Pattern, LExpr t v, Maybe SrcT.Type)]
+expandPattern triple@(pattern, lexpr@(L s _), maybeType) =
+    case pattern of
+      PVar _ -> [triple]
+      _ -> (PVar x, lexpr, maybeType) : map toDef vars
+          where
+            vars = Set.toList $ SD.boundVars pattern
+            x = concat vars
+            var = L s . Var
+            toDef y = (PVar y, L s $ Case (var x) [(pattern, var y)], Nothing)
+
+collapseDefs :: [Def t v] -> [(Pattern, LExpr t v, Maybe SrcT.Type)]
+collapseDefs = concatMap expandPattern . go [] Map.empty Map.empty
+  where
+    go output defs typs [] =
+        output ++ concatMap Map.elems [
+          Map.intersectionWithKey (\k v t -> (PVar k, v, Just t)) defs typs,
+          Map.mapWithKey (\k v -> (PVar k, v, Nothing)) (Map.difference defs typs) ]
+    go output defs typs (d:ds) =
+        case d of
+          Def (PVar name) body ->
+              go output (Map.insert name body defs) typs ds
+          Def pattern body ->
+              go ((pattern, body, Nothing) : output) defs typs ds
+          TypeAnnotation name typ ->
+              go output defs (Map.insert name typ typs) ds
+
+try :: SrcSpan -> ErrorT String IO a -> IO a
+try span computation = do
+  result <- runErrorT computation
+  case result of
+    Left msg -> error $ "\nType error " ++ show span ++ "\n" ++ msg
+    Right value -> return value
diff --git a/compiler/Type/Constrain/Literal.hs b/compiler/Type/Constrain/Literal.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/Constrain/Literal.hs
@@ -0,0 +1,21 @@
+module Type.Constrain.Literal where
+
+import SourceSyntax.Literal
+import SourceSyntax.Location
+import Type.Type
+import Type.Environment as Env
+
+constrain :: Environment -> SrcSpan -> Literal -> Type -> IO TypeConstraint
+constrain env span literal tipe =
+    do tipe' <- litType
+       return . L span $ CEqual tipe tipe'
+    where
+      prim name = Env.get env Env.types name
+
+      litType =
+          case literal of
+            IntNum _   -> VarN `fmap` var (Is Number)
+            FloatNum _ -> return (prim "Float")
+            Chr _      -> return (prim "Char")
+            Str _      -> return (TermN (App1 (prim "_List") (prim "Char")))
+            Boolean _  -> return (prim "Bool")
diff --git a/compiler/Type/Constrain/Pattern.hs b/compiler/Type/Constrain/Pattern.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/Constrain/Pattern.hs
@@ -0,0 +1,69 @@
+module Type.Constrain.Pattern where
+
+import Control.Arrow (second)
+import Control.Applicative ((<$>))
+import qualified Control.Monad as Monad
+import Control.Monad.Error
+import qualified Data.List as List
+import qualified Data.Maybe as Maybe
+import qualified Data.Map as Map
+
+import SourceSyntax.Pattern
+import SourceSyntax.PrettyPrint
+import Text.PrettyPrint (render)
+import qualified SourceSyntax.Location as Loc
+import Type.Type
+import Type.Fragment
+import Type.Environment as Env
+import qualified Type.Constrain.Literal as Literal
+
+
+constrain :: Environment -> Pattern -> Type -> ErrorT String IO Fragment
+constrain env pattern tipe =
+    let span = Loc.NoSpan (render $ pretty pattern)
+        t1 === t2 = Loc.L span (CEqual t1 t2)
+        x <? t = Loc.L span (CInstance x t)
+    in
+    case pattern of
+      PAnything -> return emptyFragment
+
+      PLiteral lit -> do
+          c <- liftIO $ Literal.constrain env span lit tipe
+          return $ emptyFragment { typeConstraint = c }
+
+      PVar name -> do
+          v <- liftIO $ var Flexible
+          return $ Fragment {
+              typeEnv    = Map.singleton name (VarN v),
+              vars       = [v],
+              typeConstraint = VarN v === tipe
+          }
+
+      PAlias name p -> do
+          fragment <- constrain env p tipe
+          return $ fragment {
+              typeEnv = Map.insert name tipe (typeEnv fragment),
+              typeConstraint = name <? tipe /\ typeConstraint fragment
+            }
+
+      PData name patterns -> do
+          (kind, cvars, args, result) <- liftIO $ freshDataScheme env name
+          let msg = concat [ "Constructor '", name, "' expects ", show kind
+                           , " argument", if kind == 1 then "" else "s"
+                           , " but was given ", show (length patterns), "." ]
+          if length patterns /= kind then throwError msg else do
+              fragment <- Monad.liftM joinFragments (Monad.zipWithM (constrain env) patterns args)
+              return $ fragment {
+                typeConstraint = typeConstraint fragment /\ tipe === result,
+                vars = cvars ++ vars fragment
+              }
+
+      PRecord fields -> do
+          pairs <- liftIO $ mapM (\name -> (,) name <$> var Flexible) fields
+          let tenv = Map.fromList (map (second VarN) pairs)
+          c <- liftIO . exists $ \t -> return (tipe === record (Map.map (:[]) tenv) t)
+          return $ Fragment {
+              typeEnv        = tenv,
+              vars           = map snd pairs,
+              typeConstraint = c
+          }
diff --git a/compiler/Type/Environment.hs b/compiler/Type/Environment.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/Environment.hs
@@ -0,0 +1,163 @@
+module Type.Environment where
+
+import Control.Applicative ((<$>), (<*>))
+import Control.Monad
+import qualified Control.Monad.State as State
+import qualified Data.Traversable as Traverse
+import qualified Data.Map as Map
+import Data.List (isPrefixOf)
+import qualified Data.UnionFind.IO as UF
+
+import qualified SourceSyntax.Type as Src
+import SourceSyntax.Module (ADT)
+import Type.Type
+
+type TypeDict = Map.Map String Type
+type VarDict = Map.Map String Variable
+
+data Environment = Environment {
+  constructor :: Map.Map String (IO (Int, [Variable], [Type], Type)),
+  aliases :: Map.Map String ([String], Src.Type),
+  types :: TypeDict,
+  value :: TypeDict
+}
+
+initialEnvironment :: [ADT] -> [(String, [String], Src.Type)] -> IO Environment
+initialEnvironment datatypes aliases = do
+    types <- makeTypes datatypes
+    let aliases' = Map.fromList $ map (\(a,b,c) -> (a,(b,c))) aliases
+        env = Environment {
+                constructor = Map.empty,
+                value = Map.empty,
+                types = types,
+                aliases = aliases' }
+
+    return $ env { constructor = makeConstructors env datatypes }
+
+makeTypes :: [ADT] -> IO TypeDict
+makeTypes datatypes = 
+    Map.fromList <$> mapM makeCtor (builtins ++ map nameAndKind datatypes)
+  where
+    nameAndKind (name, tvars, _) = (name, length tvars)
+
+    makeCtor (name, kind) = do
+      ctor <- VarN <$> namedVar Constant name
+      return (name, ctor)
+
+    tuple n = ("_Tuple" ++ show n, n)
+
+    kind n names = map (\name -> (name, n)) names
+
+    builtins :: [(String,Int)]
+    builtins = concat [ map tuple [0..9]
+                      , kind 1 ["_List"]
+                      , kind 0 ["Int","Float","Char","Bool"]
+                      ]
+
+
+makeConstructors :: Environment
+                 -> [ADT]
+                 -> Map.Map String (IO (Int, [Variable], [Type], Type))
+makeConstructors env datatypes = Map.fromList builtins
+  where
+    list t = (types env Map.! "_List") <| t
+
+    inst :: Int -> ([Type] -> ([Type], Type)) -> IO (Int, [Variable], [Type], Type)
+    inst numTVars tipe = do
+      vars <- forM [1..numTVars] $ \_ -> var Flexible
+      let (args, result) = tipe (map VarN vars)
+      return (length args, vars, args, result)
+
+    tupleCtor n =
+        let name = "_Tuple" ++ show n
+        in  (name, inst n $ \vs -> (vs, foldl (<|) (types env Map.! name) vs))
+    
+    builtins :: [ (String, IO (Int, [Variable], [Type], Type)) ]
+    builtins = [ ("[]", inst 1 $ \ [t] -> ([], list t))
+               , ("::", inst 1 $ \ [t] -> ([t, list t], list t))
+               ] ++ map tupleCtor [0..9]
+                 ++ concatMap (ctorToType env) datatypes
+
+
+ctorToType :: Environment -> ADT -> [ (String, IO (Int, [Variable], [Type], Type)) ]
+ctorToType env (name, tvars, ctors) =
+    zip (map fst ctors) (map inst ctors)
+  where
+    inst :: (String, [Src.Type]) -> IO (Int, [Variable], [Type], Type)
+    inst ctor = do
+      ((args, tipe), (dict,_)) <- State.runStateT (go ctor) (Map.empty, Map.empty)
+      return (length args, Map.elems dict, args, tipe)
+      
+
+    go :: (String, [Src.Type]) -> State.StateT (VarDict, TypeDict) IO ([Type], Type)
+    go (ctor, args) = do
+      types <- mapM (instantiator env) args
+      returnType <- instantiator env (Src.Data name (map Src.Var tvars))
+      return (types, returnType)
+
+
+get :: Environment -> (Environment -> Map.Map String a) -> String -> a
+get env subDict key = Map.findWithDefault err key (subDict env)
+  where
+    err = error $ "\nCould not find type constructor '" ++ key ++ "' while checking types."
+
+
+freshDataScheme :: Environment -> String -> IO (Int, [Variable], [Type], Type)
+freshDataScheme env name = get env constructor name
+
+instantiateType ::
+    Environment -> Src.Type -> VarDict -> IO ([Variable], Type)
+instantiateType env sourceType dict =
+  do (tipe, (dict',_)) <- State.runStateT (instantiator env sourceType) (dict, Map.empty)
+     return (Map.elems dict', tipe)
+
+instantiator :: Environment -> Src.Type
+             -> State.StateT (VarDict, TypeDict) IO Type
+instantiator env sourceType = go sourceType
+  where
+    go :: Src.Type -> State.StateT (VarDict, TypeDict) IO Type
+    go sourceType =
+      case sourceType of
+        Src.Lambda t1 t2 -> (==>) <$> go t1 <*> go t2
+
+        Src.Var x -> do
+          (dict, aliases) <- State.get
+          case (Map.lookup x dict, Map.lookup x aliases) of
+            (_, Just t) -> return t
+            (Just v, _) -> return (VarN v)
+            _ ->
+                do var <- State.liftIO $ namedVar flex x
+                   State.put (Map.insert x var dict, aliases)
+                   return (VarN var)
+                where
+                  flex | "number"     `isPrefixOf` x = Is Number
+                       | "comparable" `isPrefixOf` x = Is Comparable
+                       | "appendable" `isPrefixOf` x = Is Appendable
+                       | otherwise = Flexible
+
+        Src.Data "String" [] ->
+            return (get env types "_List" <| get env types "Char")
+
+        Src.Data name ts -> do
+          ts' <- mapM go ts
+          case (Map.lookup name (types env), Map.lookup name (aliases env)) of
+            (Just t, _) -> return $ foldl (<|) t ts'
+            (_, Just (tvars, t)) ->
+                let tvarLen = length tvars
+                    msg = "\nType alias '" ++ name ++ "' expects " ++ show tvarLen ++
+                          " type argument" ++ (if tvarLen == 1 then "" else "s") ++
+                          " but was given " ++ show (length ts')
+                in  if length ts' /= length tvars then error msg else
+                        do (dict, aliases) <- State.get
+                           let aliases' = Map.union (Map.fromList $ zip tvars ts') aliases
+                           State.put (dict, aliases')
+                           t' <- go t
+                           State.put (dict, aliases)
+                           return t'
+            _ -> error $ "\nCould not find type constructor '" ++
+                         name ++ "' while checking types."
+
+        Src.EmptyRecord -> return (TermN EmptyRecord1)
+
+        Src.Record fields ext ->
+          TermN <$> (Record1 <$> Traverse.traverse (mapM go) (Src.fieldMap fields) <*> go ext)
diff --git a/compiler/Type/Fragment.hs b/compiler/Type/Fragment.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/Fragment.hs
@@ -0,0 +1,28 @@
+module Type.Fragment where
+
+import qualified Data.List as List
+import qualified Data.Map as Map
+
+import Type.Type
+import SourceSyntax.Pattern
+import SourceSyntax.Location (noneNoDocs)
+
+data Fragment = Fragment {
+    typeEnv        :: Map.Map String Type,
+    vars           :: [Variable],
+    typeConstraint :: TypeConstraint
+} deriving Show
+
+emptyFragment = Fragment Map.empty [] (noneNoDocs CTrue)
+
+joinFragment f1 f2 = Fragment {
+    typeEnv = Map.union (typeEnv f1) (typeEnv f2),
+    vars    = vars f1 ++ vars f2,
+    typeConstraint = typeConstraint f1 /\ typeConstraint f2
+}
+
+joinFragments = List.foldl' (flip joinFragment) emptyFragment
+
+
+toScheme fragment =
+    Scheme [] (vars fragment) (typeConstraint fragment) (typeEnv fragment)
diff --git a/compiler/Type/Inference.hs b/compiler/Type/Inference.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/Inference.hs
@@ -0,0 +1,51 @@
+module Type.Inference where
+
+import qualified Data.Map as Map
+
+import qualified Type.Type as T
+import qualified Type.Environment as Env
+import qualified Type.Constrain.Expression as TcExpr
+import qualified Type.Constrain.Declaration as TcDecl
+import qualified Type.Solve as Solve
+
+import SourceSyntax.Module as Module
+import qualified SourceSyntax.Expression as Expr
+import SourceSyntax.Location (Located, noneNoDocs)
+import SourceSyntax.PrettyPrint
+import Text.PrettyPrint
+import qualified Type.State as TS
+import Control.Monad.State
+import Control.Arrow (second)
+import Transform.SortDefinitions as Sort
+
+import System.IO.Unsafe  -- Possible to switch over to the ST monad instead of
+                         -- the IO monad. I don't think that'd be worthwhile.
+
+
+infer :: Interfaces -> MetadataModule t v -> Either [Doc] (Map.Map String T.Variable)
+infer interfaces modul = unsafePerformIO $ do
+  env <- Env.initialEnvironment
+             (datatypes modul ++ concatMap iAdts (Map.elems interfaces))
+             (aliases modul ++ concatMap iAliases (Map.elems interfaces))
+  ctors <- forM (Map.keys (Env.constructor env)) $ \name ->
+               do (_, vars, args, result) <- Env.freshDataScheme env name
+                  return (name, (vars, foldr (T.==>) result args))
+
+  importedVars <-
+      forM (concatMap (Map.toList . iTypes) $ Map.elems interfaces) $ \(name,tipe) ->
+          (,) name `fmap` Env.instantiateType env tipe Map.empty
+
+  let allTypes = ctors ++ importedVars
+      vars = concatMap (fst . snd) allTypes
+      header = Map.map snd (Map.fromList allTypes)
+      environ = noneNoDocs . T.CLet [ T.Scheme vars [] (noneNoDocs T.CTrue) header ]
+
+  fvar <- T.var T.Flexible
+  constraint <- environ `fmap` TcExpr.constrain env (program modul) (T.VarN fvar)
+
+  state <- execStateT (Solve.solve constraint) TS.initialState
+  let errors = TS.sErrors state
+  if null errors
+      then return $ Right (Map.difference (TS.sSavedEnv state) header)
+      else Left `fmap` sequence (reverse errors)
+
diff --git a/compiler/Type/PrettyPrint.hs b/compiler/Type/PrettyPrint.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/PrettyPrint.hs
@@ -0,0 +1,13 @@
+
+module Type.PrettyPrint where
+
+import Text.PrettyPrint
+
+data ParensWhen = Fn | App | Never
+
+class PrettyType a where
+  pretty :: ParensWhen -> a -> Doc
+
+commaSep docs = sep (punctuate comma docs)
+
+parensIf bool doc = if bool then parens doc else doc
diff --git a/compiler/Type/Solve.hs b/compiler/Type/Solve.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/Solve.hs
@@ -0,0 +1,186 @@
+module Type.Solve (solve) where
+
+import Control.Monad
+import Control.Monad.State
+import qualified Data.UnionFind.IO as UF
+import qualified Data.Map as Map
+import qualified Data.Traversable as Traversable
+import qualified Data.Maybe as Maybe
+import qualified Data.List as List
+import Type.Type
+import Type.Unify
+import qualified Type.Environment as Env
+import qualified Type.State as TS
+import qualified Text.PrettyPrint as P
+import SourceSyntax.Location (Located(L), SrcSpan)
+
+
+-- | Every variable has rank less than or equal to the maxRank of the pool.
+--   This sorts variables into the young and old pools accordingly.
+generalize :: TS.Pool -> StateT TS.SolverState IO ()
+generalize youngPool = do
+  youngMark <- TS.uniqueMark 
+  let youngRank = TS.maxRank youngPool
+      insert dict var = do
+        desc <- liftIO $ UF.descriptor var
+        liftIO $ UF.modifyDescriptor var (\desc -> desc { mark = youngMark })
+        return $ Map.insertWith (++) (rank desc) [var] dict
+
+  -- Sort the youngPool variables by rank.
+  rankDict <- foldM insert Map.empty (TS.inhabitants youngPool)
+
+  -- get the ranks right for each entry.
+  -- start at low ranks so that we only have to pass
+  -- over the information once.
+  visitedMark <- TS.uniqueMark
+  mapM (\(poolRank, vars) -> mapM (adjustRank youngMark visitedMark poolRank) vars) (Map.toList rankDict)
+
+  -- For variables that have rank lowerer than youngRank, register them in
+  -- the old pool if they are not redundant.
+  let registerIfNotRedundant var = do
+        isRedundant <- liftIO $ UF.redundant var
+        if isRedundant then return var else TS.register var
+
+  let rankDict' = Map.delete youngRank rankDict
+  Traversable.traverse (mapM registerIfNotRedundant) rankDict'
+
+  -- For variables with rank youngRank
+  --   If rank < youngRank: register in oldPool
+  --   otherwise generalize
+  let registerIfLowerRank var = do
+        isRedundant <- liftIO $ UF.redundant var
+        if isRedundant then return () else do
+            desc <- liftIO $ UF.descriptor var
+            if rank desc < youngRank
+              then TS.register var >> return ()
+              else let flex' = if flex desc == Flexible then Rigid else flex desc
+                   in  liftIO $ UF.setDescriptor var (desc { rank = noRank, flex = flex' })
+
+  mapM registerIfLowerRank (Map.findWithDefault [] youngRank rankDict)
+
+  return ()
+
+
+-- adjust the ranks of variables such that ranks never increase as you
+-- move deeper into a variable.
+adjustRank :: Int -> Int -> Int -> Variable -> StateT TS.SolverState IO Int
+adjustRank youngMark visitedMark groupRank variable =
+    let adjust = adjustRank youngMark visitedMark groupRank in
+    do desc <- liftIO $ UF.descriptor variable
+       case () of
+         () | mark desc == youngMark ->
+                do rank' <- case structure desc of
+                              Nothing -> return groupRank
+                              Just term ->
+                                  case term of
+                                    App1 a b -> max `liftM` adjust a `ap` adjust b
+                                    Fun1 a b -> max `liftM` adjust a `ap` adjust b
+                                    Var1 x -> adjust x
+                                    EmptyRecord1 -> return outermostRank
+                                    Record1 fields extension ->
+                                        do ranks <- mapM adjust (concat (Map.elems fields))
+                                           rnk <- adjust extension
+                                           return . maximum $ rnk : ranks
+                   liftIO $ UF.setDescriptor variable (desc { mark = visitedMark, rank = rank' })
+                   return rank'
+
+            | mark desc /= visitedMark ->
+                do let rank' = min groupRank (rank desc)
+                   liftIO $ UF.setDescriptor variable (desc { mark = visitedMark, rank = rank' })
+                   return rank'
+
+            | otherwise -> return (rank desc)
+
+
+
+solve :: TypeConstraint -> StateT TS.SolverState IO ()
+solve (L span constraint) =
+  case constraint of
+    CTrue -> return ()
+
+    CSaveEnv -> TS.saveLocalEnv
+
+    CEqual term1 term2 -> do
+        t1 <- TS.flatten term1
+        t2 <- TS.flatten term2
+        unify span t1 t2
+
+    CAnd cs -> mapM_ solve cs
+
+    CLet [Scheme [] fqs constraint' _] (L _ CTrue) -> do
+        oldEnv <- TS.getEnv
+        mapM TS.introduce fqs
+        solve constraint'
+        TS.modifyEnv (\_ -> oldEnv)
+
+    CLet schemes constraint' -> do
+        oldEnv <- TS.getEnv
+        headers <- mapM (solveScheme span) schemes
+        TS.modifyEnv $ \env -> Map.unions (headers ++ [env])
+        solve constraint'
+        TS.modifyEnv (\_ -> oldEnv)
+
+    CInstance name term -> do
+        env <- TS.getEnv
+        freshCopy <-
+            case Map.lookup name env of
+              Just tipe -> TS.makeInstance tipe
+              Nothing
+                | List.isPrefixOf "Native." name -> liftIO (var Flexible)
+                | otherwise ->
+                    error ("Could not find '" ++ name ++ "' when solving type constraints.")
+
+        t <- TS.flatten term
+        unify span freshCopy t
+
+solveScheme :: SrcSpan -> TypeScheme -> StateT TS.SolverState IO (Map.Map String Variable)
+solveScheme span scheme =
+    case scheme of
+      Scheme [] [] constraint header -> do
+          solve constraint
+          Traversable.traverse TS.flatten header
+
+      Scheme rigidQuantifiers flexibleQuantifiers constraint header -> do
+          let quantifiers = rigidQuantifiers ++ flexibleQuantifiers
+          oldPool <- TS.getPool
+
+          -- fill in a new pool when working on this scheme's constraints
+          freshPool <- TS.nextRankPool
+          TS.switchToPool freshPool
+          mapM TS.introduce quantifiers
+          header' <- Traversable.traverse TS.flatten header
+          solve constraint
+
+          allDistinct span rigidQuantifiers
+          youngPool <- TS.getPool
+          TS.switchToPool oldPool
+          generalize youngPool
+          mapM (isGeneric span) rigidQuantifiers
+          return header'
+
+
+-- Checks that all of the given variables belong to distinct equivalence classes.
+-- Also checks that their structure is Nothing, so they represent a variable, not
+-- a more complex term.
+allDistinct :: SrcSpan -> [Variable] -> StateT TS.SolverState IO ()
+allDistinct span vars = do
+  seen <- TS.uniqueMark
+  let check var = do
+        desc <- liftIO $ UF.descriptor var
+        case structure desc of
+          Just _ ->
+              TS.addError span "Cannot generalize something that is not a type variable" var var
+          Nothing -> do
+            if mark desc == seen
+              then TS.addError span "Duplicate variable during generalization" var var
+              else return ()
+            liftIO $ UF.setDescriptor var (desc { mark = seen })
+  mapM_ check vars
+
+-- Check that a variable has rank == noRank, meaning that it can be generalized.
+isGeneric :: SrcSpan -> Variable -> StateT TS.SolverState IO ()
+isGeneric span var = do
+  desc <- liftIO $ UF.descriptor var
+  if rank desc == noRank
+    then return ()
+    else TS.addError span "Cannot generalize. Variable must have not have a rank." var var
diff --git a/compiler/Type/State.hs b/compiler/Type/State.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/State.hs
@@ -0,0 +1,203 @@
+module Type.State where
+
+import Type.Type
+import qualified Data.Map as Map
+import qualified Data.List as List
+import qualified Type.Environment as Env
+import qualified Data.UnionFind.IO as UF
+import Control.Monad.State
+import Control.Applicative ((<$>),(<*>), Applicative)
+import qualified Data.Traversable as Traversable
+import Text.PrettyPrint as P
+import SourceSyntax.PrettyPrint
+import SourceSyntax.Location
+
+-- Pool
+-- Holds a bunch of variables
+-- The rank of each variable is less than or equal to the pool's "maxRank"
+-- The young pool exists to make it possible to identify these vars in constant time.
+
+data Pool = Pool {
+  maxRank :: Int,
+  inhabitants :: [Variable]
+} deriving Show
+
+emptyPool = Pool { maxRank = outermostRank, inhabitants = [] }
+
+-- Keeps track of the environment, type variable pool, and a list of errors
+data SolverState = SS {
+    sEnv :: Map.Map String Variable,
+    sSavedEnv :: Map.Map String Variable,
+    sPool :: Pool,
+    sMark :: Int,
+    sErrors :: [IO P.Doc]
+}
+
+initialState = SS {
+    sEnv = Map.empty,
+    sSavedEnv = Map.empty,
+    sPool = emptyPool,
+    sMark = noMark + 1,  -- The mark must never be equal to noMark!
+    sErrors = []
+}
+
+modifyEnv  f = modify $ \state -> state { sEnv = f (sEnv state) }
+modifyPool f = modify $ \state -> state { sPool = f (sPool state) }
+
+addError span message t1 t2 =
+    modify $ \state -> state { sErrors = err : sErrors state }
+  where
+    err = makeError <$> extraPretty t1 <*> extraPretty t2
+
+    location = case span of
+                 NoSpan msg -> ""
+                 Span p1 p2 msg ->
+                     if line p1 == line p2 then " on line " ++ show (line p1)
+                     else " between lines " ++ show (line p1) ++ " and " ++ show (line p2)
+
+    display msg = if null msg then "\n"
+                  else "\n" ++ unlines (map ("        "++) $ lines msg)
+
+    src = case span of
+            NoSpan msg -> display msg
+            Span _ _ msg -> display msg
+
+    defaultMessage = "Something weird is happening with this value:"
+
+    makeError pt1 pt2 =
+        P.vcat [ P.text $ "Type error" ++ location ++ ":"
+               , P.vcat . map P.text . lines $ if null message then defaultMessage else message
+               , P.text src
+               , P.text "   Expected Type:" <+> pt1
+               , P.text "     Actual Type:" <+> pt2 <> P.text "\n"
+               ]
+
+switchToPool pool = modifyPool (\_ -> pool)
+
+getPool :: StateT SolverState IO Pool
+getPool = sPool <$> get
+
+getEnv :: StateT SolverState IO (Map.Map String Variable)
+getEnv = sEnv <$> get
+
+saveLocalEnv :: StateT SolverState IO ()
+saveLocalEnv = do
+  env <- sEnv <$> get
+  modify $ \state -> state { sSavedEnv = env }
+
+uniqueMark :: StateT SolverState IO Int
+uniqueMark = do
+  state <- get
+  let mark = sMark state
+  put $ state { sMark = mark + 1 }
+  return mark
+
+nextRankPool :: StateT SolverState IO Pool
+nextRankPool = do
+  pool <- getPool
+  return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
+
+register :: Variable -> StateT SolverState IO Variable
+register variable = do
+    modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
+    return variable
+
+introduce :: Variable -> StateT SolverState IO Variable
+introduce variable = do
+  pool <- getPool
+  liftIO $ UF.modifyDescriptor variable (\desc -> desc { rank = maxRank pool })
+  register variable
+
+flatten :: Type -> StateT SolverState IO Variable
+flatten term =
+  case term of
+    VarN v -> return v
+    TermN t -> do
+      flatStructure <- traverseTerm flatten t
+      pool <- getPool
+      var <- liftIO . UF.fresh $ Descriptor {
+               structure = Just flatStructure,
+               rank = maxRank pool,
+               flex = Flexible,
+               name = Nothing,
+               copy = Nothing,
+               mark = noMark
+             }
+      register var
+
+makeInstance :: Variable -> StateT SolverState IO Variable
+makeInstance var = do
+  alreadyCopied <- uniqueMark
+  freshVar <- makeCopy alreadyCopied var
+  restore alreadyCopied var
+  return freshVar
+
+makeCopy :: Int -> Variable -> StateT SolverState IO Variable
+makeCopy alreadyCopied variable = do
+  desc <- liftIO $ UF.descriptor variable
+  case () of
+    () | mark desc == alreadyCopied ->
+           case copy desc of
+             Just v -> return v
+             Nothing -> error "This should be impossible."
+
+       | rank desc /= noRank || flex desc == Constant ->
+           return variable
+
+       | otherwise -> do
+           pool <- getPool
+           newVar <- liftIO $ UF.fresh $ Descriptor {
+                                   structure = Nothing,
+                                   rank = maxRank pool,
+                                   mark = noMark,
+                                   flex = case flex desc of
+                                            Is s -> Is s
+                                            _ -> Flexible,
+                                   copy = Nothing,
+                                   name = case flex desc of
+                                            Rigid -> Nothing
+                                            _ -> name desc
+                                 }
+           register newVar
+
+           -- Link the original variable to the new variable. This lets us
+           -- avoid making multiple copies of the variable we are instantiating.
+           --
+           -- Need to do this before recursively copying the structure of
+           -- the variable to avoid looping on cyclic terms.
+           liftIO $ UF.modifyDescriptor variable $ \desc ->
+               desc { mark = alreadyCopied, copy = Just newVar }
+
+           -- Now we recursively copy the structure of the variable.
+           -- We have already marked the variable as copied, so we
+           -- will not repeat this work or crawl this variable again.
+           case structure desc of
+             Nothing -> return newVar
+             Just term -> do
+                 newTerm <- traverseTerm (makeCopy alreadyCopied) term
+                 liftIO $ UF.modifyDescriptor newVar $ \desc ->
+                     desc { structure = Just newTerm }
+                 return newVar
+
+restore :: Int -> Variable -> StateT SolverState IO Variable
+restore alreadyCopied variable = do
+  desc <- liftIO $ UF.descriptor variable
+  if mark desc /= alreadyCopied
+    then return variable
+    else do
+      restoredStructure <-
+          Traversable.traverse (traverseTerm (restore alreadyCopied)) (structure desc)
+      liftIO $ UF.modifyDescriptor variable $ \desc ->
+          desc { mark = noMark, rank = noRank, structure = restoredStructure }
+      return variable
+
+traverseTerm :: (Monad f, Applicative f) => (a -> f b) -> Term1 a -> f (Term1 b)
+traverseTerm f term =
+  case term of
+    App1 a b -> App1 <$> f a <*> f b
+    Fun1 a b -> Fun1 <$> f a <*> f b
+    Var1 x -> Var1 <$> f x
+    EmptyRecord1 -> return EmptyRecord1
+    Record1 fields ext ->
+        Record1 <$> Traversable.traverse (mapM f) fields <*> f ext
+
diff --git a/compiler/Type/Type.hs b/compiler/Type/Type.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/Type.hs
@@ -0,0 +1,391 @@
+module Type.Type where
+
+import qualified Data.Char as Char
+import qualified Data.List as List
+import qualified Data.Map as Map
+import qualified Data.UnionFind.IO as UF
+import Type.PrettyPrint
+import Text.PrettyPrint as P
+import System.IO.Unsafe
+import Control.Applicative ((<$>),(<*>))
+import Control.Monad.State
+import Data.Traversable (traverse)
+import SourceSyntax.Location
+import SourceSyntax.Helpers (isTuple)
+import qualified SourceSyntax.Type as Src
+
+data Term1 a
+    = App1 a a
+    | Fun1 a a
+    | Var1 a
+    | EmptyRecord1
+    | Record1 (Map.Map String [a]) a
+    deriving Show
+
+data TermN a
+    = VarN a
+    | TermN (Term1 (TermN a))
+    deriving Show
+
+record :: Map.Map String [TermN a] -> TermN a -> TermN a
+record fs rec = TermN (Record1 fs rec)
+
+type Type = TermN Variable
+type Variable = UF.Point Descriptor
+
+type SchemeName = String
+type TypeName = String
+
+type Constraint a b = Located (BasicConstraint a b)
+data BasicConstraint a b
+    = CTrue
+    | CSaveEnv
+    | CEqual a a
+    | CAnd [Constraint a b]
+    | CLet [Scheme a b] (Constraint a b)
+    | CInstance SchemeName a
+    deriving Show
+
+data Scheme a b = Scheme {
+    rigidQuantifiers :: [b],
+    flexibleQuantifiers :: [b],
+    constraint :: Constraint a b,
+    header :: Map.Map String a
+} deriving Show
+
+type TypeConstraint = Constraint Type Variable
+type TypeScheme = Scheme Type Variable
+
+monoscheme headers = Scheme [] [] (noneNoDocs CTrue) headers
+
+infixl 8 /\
+
+(/\) :: Constraint a b -> Constraint a b -> Constraint a b
+a@(L s1 c1) /\ b@(L s2 c2) =
+    case (c1, c2) of
+      (CTrue, _) -> b
+      (_, CTrue) -> a
+      _ -> mergeOldDocs a b (CAnd [a,b])
+
+infixr 9 ==>
+(==>) :: Type -> Type -> Type
+a ==> b = TermN (Fun1 a b)
+
+f <| a = TermN (App1 f a)
+
+data Descriptor = Descriptor {
+    structure :: Maybe (Term1 Variable),
+    rank :: Int,
+    flex :: Flex,
+    name :: Maybe TypeName,
+    copy :: Maybe Variable,
+    mark :: Int
+} deriving Show
+
+noRank = -1
+outermostRank = 0 :: Int
+
+noMark = 0
+initialMark = 1
+
+data Flex = Rigid | Flexible | Constant | Is SuperType
+     deriving (Show, Eq)
+
+data SuperType = Number | Comparable | Appendable
+     deriving (Show, Eq)
+
+namedVar flex name = UF.fresh $ Descriptor {
+    structure = Nothing,
+    rank = noRank,
+    flex = flex,
+    name = Just name,
+    copy = Nothing,
+    mark = noMark
+  }
+
+var flex = UF.fresh $ Descriptor {
+    structure = Nothing,
+    rank = noRank,
+    flex = flex,
+    name = Nothing,
+    copy = Nothing,
+    mark = noMark
+  }
+
+structuredVar structure = UF.fresh $ Descriptor {
+    structure = Just structure,
+    rank = noRank,
+    flex = Flexible,
+    name = Nothing,
+    copy = Nothing,
+    mark = noMark
+  }
+
+
+-- ex qs constraint == exists qs. constraint
+ex :: [Variable] -> TypeConstraint -> TypeConstraint
+ex fqs constraint@(L s _) = L s $ CLet [Scheme [] fqs constraint Map.empty] (L s CTrue)
+
+-- fl qs constraint == forall qs. constraint
+fl :: [Variable] -> TypeConstraint -> TypeConstraint
+fl rqs constraint@(L s _) = L s $ CLet [Scheme rqs [] constraint Map.empty] (L s CTrue)
+
+exists :: (Type -> IO TypeConstraint) -> IO TypeConstraint
+exists f = do
+  v <- var Flexible
+  ex [v] <$> f (VarN v)
+
+
+instance Show a => Show (UF.Point a) where
+  show point = unsafePerformIO $ fmap show (UF.descriptor point)
+
+
+instance PrettyType a => PrettyType (UF.Point a) where
+  pretty when point = unsafePerformIO $ fmap (pretty when) (UF.descriptor point)
+
+
+instance PrettyType a => PrettyType (Located a) where
+  pretty when (L _ e) = pretty when e
+
+
+instance PrettyType a => PrettyType (Term1 a) where
+  pretty when term =
+    let prty = pretty Never in
+    case term of
+      App1 f x | P.render px == "_List" -> P.brackets (pretty Never x)
+               | otherwise -> parensIf needed (px <+> pretty App x)
+        where
+          px = prty f
+          needed = case when of
+                     App -> True
+                     _ -> False
+
+      Fun1 arg body ->
+          parensIf needed (pretty Fn arg <+> P.text "->" <+> prty body)
+        where
+          needed = case when of
+                     Never -> False
+                     _ -> True
+
+      Var1 x -> prty x
+
+      EmptyRecord1 -> P.braces P.empty
+
+      Record1 fields ext -> P.braces (extend <+> commaSep prettyFields)
+        where
+          prettyExt = prty ext
+          extend | P.render prettyExt == "{}" = P.empty
+                 | otherwise = prettyExt <+> P.text "|"
+          mkPretty f t = P.text f <+> P.text ":" <+> prty t
+          prettyFields = concatMap (\(f,ts) -> map (mkPretty f) ts) (Map.toList fields)
+
+
+instance PrettyType a => PrettyType (TermN a) where
+  pretty when term =
+    case term of
+      VarN x -> pretty when x
+      TermN t1 -> pretty when t1
+
+
+instance PrettyType Descriptor where
+  pretty when desc =
+    case (structure desc, name desc) of
+      (Just term, _) -> pretty when term
+      (_, Just name) -> if not (isTuple name) then P.text name else
+                            P.parens . P.text $ replicate (read (drop 6 name) - 1) ','
+      _ -> P.text "?"
+
+
+instance (PrettyType a, PrettyType b) => PrettyType (BasicConstraint a b) where
+  pretty _ constraint =
+    let prty = pretty Never in
+    case constraint of
+      CTrue -> P.text "True"
+      CSaveEnv -> P.text "SaveTheEnvironment!!!"
+      CEqual a b -> prty a <+> P.text "=" <+> prty b
+      CAnd [] -> P.text "True"
+
+      CAnd cs ->
+        P.parens . P.sep $ P.punctuate (P.text " and") (map (pretty Never) cs)
+
+      CLet [Scheme [] fqs constraint header] (L _ CTrue) | Map.null header ->
+          P.sep [ binder, pretty Never c ]
+        where
+          mergeExists vs (L _ c) =
+            case c of
+              CLet [Scheme [] fqs' c' _] (L _ CTrue) -> mergeExists (vs ++ fqs') c'
+              _ -> (vs, c)
+
+          (fqs', c) = mergeExists fqs constraint
+
+          binder = if null fqs' then P.empty else
+                     P.text "\x2203" <+> P.hsep (map (pretty Never) fqs') <> P.text "."
+
+      CLet schemes constraint ->
+        P.fsep [ P.hang (P.text "let") 4 (P.brackets . commaSep $ map (pretty Never) schemes)
+               , P.text "in", pretty Never constraint ]
+
+      CInstance name tipe ->
+        P.text name <+> P.text "<" <+> prty tipe
+
+instance (PrettyType a, PrettyType b) => PrettyType (Scheme a b) where
+  pretty _ (Scheme rqs fqs (L _ constraint) headers) =
+      P.sep [ forall, cs, headers' ]
+    where
+      prty = pretty Never
+
+      forall = if null rqs && null fqs then P.empty else
+               P.text "\x2200" <+> frees <+> rigids
+
+      frees = P.hsep $ map prty fqs
+      rigids = if null rqs then P.empty else P.braces . P.hsep $ map prty rqs
+
+      cs = case constraint of
+             CTrue -> P.empty
+             CAnd [] -> P.empty
+             _ -> P.brackets (pretty Never constraint)
+
+      headers' = if Map.size headers > 0 then dict else P.empty
+      dict = P.parens . commaSep . map prettyPair $ Map.toList headers
+      prettyPair (n,t) = P.text n <+> P.text ":" <+> pretty Never t
+
+
+extraPretty :: (PrettyType t, Crawl t) => t -> IO Doc
+extraPretty t = pretty Never <$> addNames t
+
+addNames :: (Crawl t) => t -> IO t
+addNames value = do
+    (rawVars, _, _, _) <- execStateT (crawl getNames value) ([], 0, 0, 0)
+    let vars = map head . List.group $ List.sort rawVars
+        suffix s = map (++s) (map (:[]) ['a'..'z'])
+        allVars = concatMap suffix $ ["","'","_"] ++ map show [0..]
+        okayVars = filter (`notElem` vars) allVars
+    runStateT (crawl rename value) (okayVars, 0, 0, 0)
+    return value
+  where
+    getNames desc state@(vars, a, b, c) =
+        let name' = name desc in
+        case name' of
+          Just var -> (name', (var:vars, a, b, c))
+          Nothing -> (name', state)
+
+    rename desc state@(vars, a, b, c) =
+      case name desc of
+        Just var -> (Just var, state)
+        Nothing ->
+            case flex desc of
+              Is Number     -> (Just $ "number"     ++ replicate a '\'', (vars, a+1, b, c))
+              Is Comparable -> (Just $ "comparable" ++ replicate b '\'', (vars, a, b+1, c))
+              Is Appendable -> (Just $ "appendable" ++ replicate c '\'', (vars, a, b, c+1))
+              _             -> (Just $ head vars, (tail vars, a, b, c))
+
+
+type CrawlState = ([String], Int, Int, Int)
+
+-- Code for traversing all the type data-structures and giving
+-- names to the variables embedded deep in there.
+class Crawl t where
+  crawl :: (Descriptor -> CrawlState -> (Maybe TypeName, CrawlState))
+        -> t
+        -> StateT CrawlState IO t
+
+instance Crawl a => Crawl (Located a) where
+  crawl nextState (L s e) = L s <$> crawl nextState e
+
+instance (Crawl t, Crawl v) => Crawl (BasicConstraint t v) where
+  crawl nextState constraint = 
+    let rnm = crawl nextState in
+    case constraint of
+      CTrue -> return CTrue
+      CSaveEnv -> return CSaveEnv
+      CEqual a b -> CEqual <$> rnm a <*> rnm b
+      CAnd cs -> CAnd <$> crawl nextState cs
+      CLet schemes c -> CLet <$> crawl nextState schemes <*> crawl nextState c 
+      CInstance name tipe -> CInstance name <$> rnm tipe
+
+instance Crawl a => Crawl [a] where
+  crawl nextState list = mapM (crawl nextState) list
+
+instance (Crawl t, Crawl v) => Crawl (Scheme t v) where
+  crawl nextState (Scheme rqs fqs c headers) =
+    let rnm = crawl nextState in
+    Scheme <$> rnm rqs <*> rnm fqs <*> crawl nextState c <*> return headers
+
+instance Crawl t => Crawl (TermN t) where
+  crawl nextState tipe =
+    case tipe of
+      VarN x -> VarN <$> crawl nextState x
+      TermN term -> TermN <$> crawl nextState term
+
+instance Crawl t => Crawl (Term1 t) where
+  crawl nextState term =
+     let rnm = crawl nextState in
+     case term of
+      App1 a b -> App1 <$> rnm a <*> rnm b
+      Fun1 a b -> Fun1 <$> rnm a <*> rnm b
+      Var1 a -> Var1 <$> rnm a
+      EmptyRecord1 -> return EmptyRecord1
+      Record1 fields ext ->
+          Record1 <$> traverse (mapM rnm) fields <*> rnm ext
+
+instance Crawl a => Crawl (UF.Point a) where
+  crawl nextState point = do
+    desc <- liftIO $ UF.descriptor point
+    desc' <- crawl nextState desc
+    liftIO $ UF.setDescriptor point desc'
+    return point
+
+instance Crawl Descriptor where
+  crawl nextState desc = do
+    state <- get
+    let (name', state') = nextState desc state
+    structure' <- traverse (crawl nextState) (structure desc)
+    put state'
+    return $ desc { name = name', structure = structure' }
+
+               
+toSrcType :: Variable -> IO Src.Type
+toSrcType variable = do
+  desc <- UF.descriptor =<< addNames variable
+  case structure desc of
+    Just term ->
+        case term of
+          App1 a b -> do
+            Src.Data name ts <- toSrcType a
+            b' <- toSrcType b
+            return (Src.Data name (ts ++ [b']))
+          Fun1 a b -> Src.Lambda <$> toSrcType a <*> toSrcType b
+          Var1 a -> toSrcType a
+          EmptyRecord1 -> return Src.EmptyRecord
+          Record1 fs ext -> do
+            fs' <- traverse (mapM toSrcType) fs
+            let fs'' = concat [ map ((,) name) ts | (name,ts) <- Map.toList fs' ]
+            Src.Record fs'' <$> toSrcType ext
+    Nothing ->
+        case name desc of
+          Just x@(c:cs) | Char.isLower c -> return (Src.Var x)
+                        | otherwise      -> return (Src.Data x [])
+          Nothing ->
+              error $ concat
+                        [ "Problem converting the following type "
+                        , "from a type-checker type to a source-syntax type:"
+                        , P.render (pretty Never variable) ]
+
+
+data AppStructure = List Variable | Tuple [Variable] | Other
+
+collectApps :: Variable -> IO AppStructure
+collectApps variable = go [] variable
+  where
+    go vars variable = do
+      desc <- UF.descriptor variable
+      case (structure desc, vars) of
+        (Nothing, [v] ) -> case name desc of
+                             Just "_List" -> return (List v)
+                             _ -> return Other
+        (Nothing,  vs ) -> case name desc of
+                             Just ctor | isTuple ctor -> return (Tuple vs)
+                             _ -> return Other
+        (Just term, vs) -> case term of
+                             App1 a b -> go (vars ++ [b]) a
+                             _ -> return Other
diff --git a/compiler/Type/Unify.hs b/compiler/Type/Unify.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Type/Unify.hs
@@ -0,0 +1,195 @@
+module Type.Unify (unify) where
+
+import Type.Type
+import qualified Data.UnionFind.IO as UF
+import qualified Data.Map as Map
+import qualified Type.State as TS
+import Control.Arrow (first,second)
+import Control.Monad.State
+import SourceSyntax.Location
+import Type.PrettyPrint
+import Text.PrettyPrint (render)
+
+unify :: SrcSpan -> Variable -> Variable -> StateT TS.SolverState IO ()
+unify span variable1 variable2 = do
+  equivalent <- liftIO $ UF.equivalent variable1 variable2
+  if equivalent then return ()
+                else actuallyUnify span variable1 variable2
+
+actuallyUnify :: SrcSpan -> Variable -> Variable -> StateT TS.SolverState IO ()
+actuallyUnify span variable1 variable2 = do
+  desc1 <- liftIO $ UF.descriptor variable1
+  desc2 <- liftIO $ UF.descriptor variable2
+  let unify' = unify span
+
+      name' :: Maybe String
+      name' = case (name desc1, name desc2) of
+                (Just name1, Just name2) ->
+                    case (flex desc1, flex desc2) of
+                      (_, Flexible) -> Just name1
+                      (Flexible, _) -> Just name2
+                      (Is Number, Is _) -> Just name1
+                      (Is _, Is Number) -> Just name2
+                      (Is _, Is _) -> Just name1
+                      (_, _) -> Nothing
+                (Just name1, _) -> Just name1
+                (_, Just name2) -> Just name2
+                _ -> Nothing
+
+      flex' :: Flex
+      flex' = case (flex desc1, flex desc2) of
+                (f, Flexible) -> f
+                (Flexible, f) -> f
+                (Is Number, Is _) -> Is Number
+                (Is _, Is Number) -> Is Number
+                (Is super, Is _) -> Is super
+                (_, _) -> Flexible
+
+      rank' :: Int
+      rank' = min (rank desc1) (rank desc2)
+
+      merge1 :: StateT TS.SolverState IO ()
+      merge1 = liftIO $ do
+        if rank desc1 < rank desc2 then UF.union variable2 variable1
+                                   else UF.union variable1 variable2
+        UF.modifyDescriptor variable1 $ \desc ->
+            desc { structure = structure desc1, flex = flex', name = name' }
+
+      merge2 :: StateT TS.SolverState IO ()
+      merge2 = liftIO $ do
+        if rank desc1 < rank desc2 then UF.union variable2 variable1
+                                   else UF.union variable1 variable2
+        UF.modifyDescriptor variable2 $ \desc ->
+            desc { structure = structure desc2, flex = flex', name = name' }
+
+      merge = if rank desc1 < rank desc2 then merge1 else merge2
+
+      fresh :: Maybe (Term1 Variable) -> StateT TS.SolverState IO Variable
+      fresh structure = do
+        var <- liftIO . UF.fresh $ Descriptor {
+                 structure = structure, rank = rank', flex = flex',
+                 name = name', copy = Nothing, mark = noMark
+               }
+        TS.register var
+
+      flexAndUnify var = do
+        liftIO $ UF.modifyDescriptor var $ \desc -> desc { flex = Flexible }
+        unify' variable1 variable2
+
+      unifyNumber svar name
+          | name `elem` ["Int","Float"] = flexAndUnify svar
+          | otherwise = TS.addError span "Expecting a number (Int or Float)" variable1 variable2
+
+      comparableError str = TS.addError span (str ++ msg) variable1 variable2
+          where msg = "Expecting something comparable such as an\n" ++
+                      "Int, Float, Char, or a list or tuple of comparables."
+
+      unifyComparable var name
+          | name `elem` ["Int","Float","Char"] = flexAndUnify var
+          | otherwise = comparableError ""
+
+      unifyComparableStructure varSuper varFlex =
+          do struct <- liftIO $ collectApps varFlex
+             case struct of
+               Other -> comparableError ""
+               List v -> do flexAndUnify varSuper
+                            unify' v =<< liftIO (var $ Is Comparable)
+               Tuple vs
+                   | length vs > 6 ->
+                       comparableError "Cannot compare a tuple with more than 6 elements.\n"
+                   | otherwise -> 
+                       do flexAndUnify varSuper
+                          cmpVars <- liftIO $ forM [1..length vs] $ \_ -> var (Is Comparable)
+                          zipWithM_ unify' vs cmpVars
+
+      unifyAppendable varSuper varFlex =
+          do struct <- liftIO $ collectApps varFlex
+             case struct of
+               List _ -> flexAndUnify varSuper
+               _ -> comparableError ""
+
+      rigidError variable = TS.addError span msg variable1 variable2
+          where
+            msg = concat
+                  [ "Cannot unify rigid type variable '", render (pretty Never variable), "'.\n"
+                  , "It is likely that a type annotation is not general enough." ]
+
+      superUnify =
+          case (flex desc1, flex desc2, name desc1, name desc2) of
+            (Is super1, Is super2, _, _)
+                | super1 == super2 -> merge
+            (Is Number, Is Comparable, _, _) -> merge1
+            (Is Comparable, Is Number, _, _) -> merge2
+                   
+            (Is Number, _, _, Just name) -> unifyNumber variable1 name
+            (_, Is Number, Just name, _) -> unifyNumber variable2 name
+
+            (Is Comparable, _, _, Just name) -> unifyComparable variable1 name
+            (_, Is Comparable, Just name, _) -> unifyComparable variable2 name
+            (Is Comparable, _, _, _) -> unifyComparableStructure variable1 variable2
+            (_, Is Comparable, _, _) -> unifyComparableStructure variable2 variable1
+
+            (Is Appendable, _, _, Just "Text.Text") -> flexAndUnify variable1
+            (_, Is Appendable, Just "Text.Text", _) -> flexAndUnify variable2
+            (Is Appendable, _, _, _) -> unifyAppendable variable1 variable2
+            (_, Is Appendable, _, _) -> unifyAppendable variable2 variable1
+
+            (Rigid, _, _, _) -> rigidError variable1
+            (_, Rigid, _, _) -> rigidError variable2
+            _ -> TS.addError span "" variable1 variable2
+
+  case (structure desc1, structure desc2) of
+    (Nothing, Nothing) | flex desc1 == Flexible && flex desc1 == Flexible -> merge
+    (Nothing, _) | flex desc1 == Flexible -> merge2
+    (_, Nothing) | flex desc2 == Flexible -> merge1
+
+    (Just (Var1 v), _) -> unify' v variable2
+    (_, Just (Var1 v)) -> unify' v variable1
+
+    (Nothing, _) -> superUnify
+    (_, Nothing) -> superUnify
+
+    (Just type1, Just type2) ->
+        case (type1,type2) of
+          (App1 term1 term2, App1 term1' term2') ->
+              do merge
+                 unify' term1 term1'
+                 unify' term2 term2'
+          (Fun1 term1 term2, Fun1 term1' term2') ->
+              do merge
+                 unify' term1 term1'
+                 unify' term2 term2'
+
+          (EmptyRecord1, EmptyRecord1) ->
+              return ()
+
+          (Record1 fields ext, EmptyRecord1) | Map.null fields -> unify' ext variable2
+          (EmptyRecord1, Record1 fields ext) | Map.null fields -> unify' ext variable1
+
+          (Record1 fields1 ext1, Record1 fields2 ext2) ->
+              do sequence . concat . Map.elems $ Map.intersectionWith (zipWith unify') fields1 fields2
+                 let mkRecord fs ext = liftIO . structuredVar $ Record1 fs ext
+                 case (Map.null fields1', Map.null fields2') of
+                   (True , True ) -> unify' ext1 ext2
+                   (True , False) -> do
+                      record2' <- mkRecord fields2' ext2
+                      unify' ext1 record2'
+                   (False, True ) -> do
+                      record1' <- mkRecord fields1' ext1
+                      unify' record1' ext2
+                   (False, False) -> do
+                      record1' <- mkRecord fields1' =<< liftIO (var Flexible)
+                      record2' <- mkRecord fields2' =<< liftIO (var Flexible)
+                      unify' record1' ext2
+                      unify' ext1 record2'
+              where
+                fields1' = unmerged fields1 fields2
+                fields2' = unmerged fields2 fields1
+
+                unmerged a b = Map.filter (not . null) $ Map.union (Map.intersectionWith eat a b) a
+
+                eat (x:xs) (y:ys) = eat xs ys
+                eat xs ys = xs
+
+          _ -> TS.addError span "" variable1 variable2
+
diff --git a/compiler/Types/Alias.hs b/compiler/Types/Alias.hs
deleted file mode 100644
--- a/compiler/Types/Alias.hs
+++ /dev/null
@@ -1,139 +0,0 @@
-
-module Types.Alias (dealias, get, mistakes) where
-
-import Ast
-import Control.Arrow (second)
-import Data.List (group,sort)
-import qualified Data.Map as Map
-import qualified Data.Set as Set
-import Types.Substitutions (subst)
-import Types.Types
-
-builtins :: [(String,([X],Type))]
-builtins =
-    let touch = ("t0", time) : map (flip (,) int) ["x","y","x0","y0","id"]
-        state = [("string", string), ("selectionStart", int), ("selectionEnd", int)]
-        line  = [("color", tipe "Color"), ("width", float),
-                 ("cap", tipe "LineCap"), ("join", tipe "LineJoin"),
-                 ("miterLimit", float),   ("dashing", listOf int),
-                 ("dashOffset", int)]
-        makeRecord fields =
-            RecordT (Map.fromList $ map (second (:[])) fields) EmptyRecord
-    in  [ ("String", ([], listOf char)),
-          ("Time", ([], float)),
-          ("KeyCode", ([], int)),
-          ("Touch", ([], makeRecord touch)),
-          ("FieldState", ([], makeRecord state)),
-          ("LineStyle", ([], makeRecord line))
-        ]
-
-get :: [Statement] -> Map.Map String ([X],Type)
-get stmts = Map.fromList (builtins ++ concatMap getAlias stmts)
-    where getAlias stmt = case stmt of
-                            TypeAlias alias xs t -> [(alias, (xs,t))]
-                            _ -> []
-
-dealias :: Map.Map String ([X],Type) -> Type -> Type
-dealias aliases t =
-  let f = dealias aliases in
-  case t of
-    ADT name ts -> case Map.lookup name aliases of
-                     Just (xs,t) -> f (subst (zip xs ts) t)
-                     Nothing -> ADT name (map f ts)
-    LambdaT t u -> LambdaT (f t) (f u)
-    RecordT r t -> RecordT (Map.map (map f) r) (f t)
-    _ -> t
-
-mistakes :: [Statement] -> [String]
-mistakes stmts = badKinds stmts ++ dups stmts ++ badOrder stmts
-
-badKinds :: [Statement] -> [String]
-badKinds stmts = map msg (concatMap badS stmts)
-  where
-    msg x = "Type Error: Type alias '" ++ x ++
-            "' was given the wrong number of arguments."
-
-    badT :: Type -> [String]
-    badT t =
-      case t of
-        ADT name ts ->
-          case Map.lookup name (get stmts) of
-            Just (xs,t) | length xs == length ts -> []
-                        | otherwise -> [name]
-            Nothing -> concatMap badT ts
-        LambdaT t u -> badT t ++ badT u
-        RecordT r t -> badT t ++ concatMap badT (concat (Map.elems r))
-        _ -> []
-
-    badS :: Statement -> [String]
-    badS s =
-      case s of
-        Datatype _ _ tcs -> concatMap badT (concatMap snd tcs)
-        ExportEvent _ _ tipe   -> badT tipe
-        ImportEvent _ _ _ tipe -> badT tipe
-        TypeAnnotation _ tipe  -> badT tipe
-        TypeAlias _ _ tipe     -> badT tipe
-        Definition _ -> []
-
-annotation :: Statement -> [String]
-annotation s =
-    case s of
-      TypeAnnotation name _ -> [name]
-      _ -> []
-
-definition :: Statement -> [String]
-definition s =
-    case s of
-      Definition d -> [defName d]
-      _ -> []
-
-defName :: Def -> String
-defName d =
-    case d of
-      FnDef n _ _   -> n
-      OpDef n _ _ _ -> n
-
-dups :: [Statement] -> [String]
-dups stmts = map defMsg (dup definition) ++ map annMsg (dup annotation)
-    where
-      dup :: (Statement -> [String]) -> [String]
-      dup f = map head . filter ((>1) . length) . group . sort $ concatMap f stmts
-
-      msg = "Syntax Error: There can only be one "
-      defMsg x = msg ++ "top-level definition of '" ++ x ++ "'."
-      annMsg x = msg ++ "type annotation for '" ++ x ++ "'."
-
-badOrder :: [Statement] -> [String]
-badOrder stmts = map msg $ missings (sort $ expectedPairs as ds) (sort $ actualPairs stmts)
-    where
-      msg x = "Syntax Error: The type annotation for '" ++ x ++
-              "' must be directly above its definition."
-      as = sort $ concatMap annotation stmts
-      ds = sort $ concatMap definition stmts
-
-      expectedPairs :: [String] -> [String] -> [String]
-      expectedPairs as ds =
-          case (as,ds) of
-            (x:xs, y:ys) -> case compare x y of
-                              LT -> expectedPairs xs (y:ys)
-                              EQ -> x : expectedPairs xs ys
-                              GT -> expectedPairs (x:xs) ys
-            ( _  ,  _  ) -> []
-
-      actualPairs :: [Statement] -> [String]
-      actualPairs stmts =      
-          case stmts of
-            TypeAnnotation n _ : Definition d : rest ->
-                (if n == defName d then [n] else []) ++ actualPairs rest
-            t:s:rest -> actualPairs (s:rest)
-            _ -> []
-
-      missings :: [String] -> [String] -> [String]
-      missings expected actual =
-          case (expected, actual) of
-            (e:es, a:as) -> case compare e a of
-                              LT -> e : missings es (a:as)
-                              EQ -> missings es as
-                              GT -> a : missings (e:es) as
-            ( [] ,  _  ) -> actual
-            (  _ ,  [] ) -> expected
diff --git a/compiler/Types/Constrain.hs b/compiler/Types/Constrain.hs
deleted file mode 100644
--- a/compiler/Types/Constrain.hs
+++ /dev/null
@@ -1,318 +0,0 @@
-
-module Types.Constrain (constrain) where
-
-import Control.Arrow (second)
-import Control.Monad (liftM,mapM,zipWithM,foldM)
-import Control.Monad.State (evalState)
-import Data.Char (isDigit)
-import Data.List (foldl',sort,group,isPrefixOf,intercalate,isSuffixOf)
-import qualified Data.Map as Map
-import qualified Data.Set as Set
-
-import Ast
-import Context
-import Guid
-
-import Types.Types
-import qualified Types.Substitutions as Subs
-
-beta = VarT `liftM` guid
-unionA = Map.unionWith (++)
-unionsA = Map.unionsWith (++)
-
-getAliases imports hints = concatMap aliasesFrom imports
-  where aliasesFrom (name,method) =
-            let values = concatMap (getValue name) hints
-            in  case method of
-                  As alias -> map (\(n,t) -> (alias ++ "." ++ n, t)) values
-                  Hiding vs -> filter (\(n,t) -> n `notElem` vs) values
-                  Importing vs -> filter (\(n,t) -> n `elem` vs) values
-        getValue inModule (name,tipe) =
-            case inModule `isPrefixOf` name of
-              True  -> [ (drop (length inModule + 1) name, tipe) ]
-              False -> []
-
-findAmbiguous hints assumptions continue =
- let potentialDups = map head . filter (\g -> length g > 1) . group . sort $
-                     filter (elem '.') hints
-     dups = filter (\k -> Map.member k assumptions) potentialDups
- in case dups of
-      n:_ -> return . Left $ "Error: Ambiguous occurrence of '" ++ n ++
-             "' could refer to " ++
-             intercalate ", " (filter (isSuffixOf n) hints)
-      _ -> continue
-
-mergeSchemes :: [Map.Map String Scheme]
-             -> GuidCounter (TVarMap, ConstraintSet, Map.Map String Scheme)
-mergeSchemes schmss = do (ass,css,sss) <- unzip3 `liftM` mapM split kvs
-                         return (Map.unions ass, Set.unions css, Map.unions sss)
-  where
-    kvs = Map.toList $ Map.unionsWith (++) (map (Map.map (:[])) schmss)
-    split (k,vs) =
-      let ps = zipWith (\s v -> (s++k,v)) (map (flip replicate '_') [0..]) vs
-          eq t u = C (Just $ msg ++ k) NoSpan (VarT t :=: VarT u)
-          msg = "the definition of "
-      in  do xs <- mapM (\_ -> guid) vs
-             return ( Map.fromList $ zip (map fst ps) (map (:[]) xs)
-                    , case xs of
-                        t:ts -> Set.fromList $ zipWith eq (t:ts) ts
-                        []   -> Set.empty
-                    , Map.fromList ps )
-
-constrain typeHints (Module _ _ imports stmts) = do
-  (ass,css,schemess) <- unzip3 `liftM` mapM stmtGen stmts
-  aliasHints <- getAliases imports `liftM` typeHints
-  (as', cs', schemes) <- mergeSchemes schemess
-  let constraints = Set.unions (cs':css)
-      as = unionsA (as':ass)
-      allHints = Map.union schemes (Map.fromList aliasHints)
-      insert as n = do v <- guid; return $ Map.insertWith' (\_ x -> x) n [v] as
-  assumptions <- foldM insert as (Map.keys schemes)
-  findAmbiguous (map fst aliasHints) assumptions $ do
-    let f k s vs = map (\v -> C (Just k) NoSpan $ v :<<: s) vs
-        cs = concat . Map.elems $ Map.intersectionWithKey f allHints assumptions
-        escapees = Map.keys $ Map.difference assumptions allHints
-    return $ case escapees of
-               _  -> Right (Set.toList constraints ++ cs)
-               --_  -> Left ("Undefined variable(s): " ++ intercalate ", " escapees)
-
-type TVarMap = Map.Map String [X]
-type ConstraintSet = Set.Set (Context Constraint)
-
-ctx e span = C (Just $ show e) span
-
-gen :: CExpr -> GuidCounter (TVarMap, ConstraintSet, Type)
-gen (C _ span expr) =
-  let ctx' = C (Just $ show expr) span in
-  case expr of
-    Var x ->
-        do b <- guid
-           return (Map.singleton x [b], Set.empty, VarT b)
-
-    App e1 e2 ->
-        do (a1,c1,t1) <- gen e1
-           (a2,c2,t2) <- gen e2
-           b <- beta
-           return ( unionA a1 a2
-                  , Set.unions [c1,c2
-                               ,Set.singleton . ctx' $ t1 :=: (LambdaT t2 b)]
-                  , b )
-
-    Lambda x e ->
-        do (a,c,t) <- gen e
-           b <- beta
-           v <- guid
-           return ( Map.delete x a
-                  , Set.union c . Set.fromList .
-                    map (\x -> ctx' $ VarT x :=: b) $
-                    Map.findWithDefault [v] x a
-                  , LambdaT b t )
-
-    Let defs e ->
-        do (as,cs,t) <- gen e
-           (ass, schemes) <- liftM unzip (mapM defScheme defs)
-           let assumptions = unionsA (as:ass)
-               getName d = case d of FnDef f _ _    -> f
-                                     OpDef op _ _ _ -> op
-               names = map getName defs
-               genCs name s = do
-                 v <- guid
-                 let vs = Map.findWithDefault [v] name assumptions
-                 return $ map (\x -> ctx name span $ x :<<: s) vs
-           cs' <- zipWithM genCs names schemes
-           return ( foldr Map.delete assumptions names
-                  , Set.union (Set.fromList . concat $ cs') cs
-                  , t )
-
-    Case e cases ->
-        do (as,cs,t) <- gen e
-           (ass,css,ts) <- liftM unzip3 $ mapM (caseGen t) cases
-           return ( unionsA $ as:ass
-                  , let cases' = map snd cases
-                        ctxs = zipWith epos cases' (tail cases')
-                        csts = zipWith (:=:) ts (tail ts)
-                        cs' = Set.fromList (zipWith ($) ctxs csts)
-                    in  Set.unions $ cs' : cs : css
-                  , head ts)
-
-    If e1 e2 e3 ->
-        do (a1,c1,t1) <- gen e1
-           (a2,c2,t2) <- gen e2
-           (a3,c3,t3) <- gen e3
-           return ( unionsA [a1,a2,a3]
-                  , let c4 = Set.fromList [ ctx e1 span (t1 :=: bool)
-                                          , ctx' (t2 :=: t3)   ]
-                    in  Set.unions [c1,c2,c3,c4]
-                  , t2 )
-
-    Data name es ->
-        gen $ foldl' (\f x -> epos f x $ App f x) (ctx' $ Var name) es
-
-    Binop op e1 e2 ->
-        gen $ ctx' (App (ctx' $ App (ctx' $ Var op) e1) e2)
-
-    Access e label ->
-        do (as,cs,rtype) <- gen e
-           t <- beta
-           rtype' <- beta
-           let fs = Map.singleton label [t]
-               c = (ctx' (RecordT fs rtype' :=: rtype))
-           return (as, Set.insert c cs, t)
-
-    Remove e x -> 
-        do (as,cs,rtype) <- gen e
-           t <- beta
-           rtype' <- beta
-           let c = (ctx' (RecordT (Map.singleton x [t]) rtype' :=: rtype))
-           return (as, Set.insert c cs, rtype')
-
-    Insert e x v -> 
-        do (eas,ecs,etype) <- gen e
-           (vas,vcs,vtype) <- gen v
-           return ( unionA eas vas
-                  , Set.union ecs vcs
-                  , RecordT (Map.singleton x [vtype]) etype )
-
-    Modify record fields ->
-        do (ras,rcs,rtype) <- gen record
-           (ass,css,newTs) <- unzip3 `liftM` mapM gen (map snd fields)
-           oldTs <- mapM (\_ -> beta) fields
-           rtype' <- beta
-           let rT ts = RecordT (recordT (zip (map fst fields) ts)) rtype'
-               c = Set.singleton (ctx' (rtype :=: rT oldTs))
-           return ( unionsA (ras:ass), Set.unions (c : rcs : css), rT newTs )
-
-    Record fields ->
-        let insert label tipe = Map.insertWith (++) label [tipe]
-            getScheme (f,args,e) = do
-              (as, _, (label, Forall _ cs  tipe)) <- defGenHelp f args e
-              return (as, cs, insert label tipe)
-        in  do (ass, css, fs) <- unzip3 `liftM` mapM getScheme fields
-               return ( unionsA ass
-                      , Set.fromList (concat css)
-                      , RecordT (foldr ($) Map.empty fs) EmptyRecord )
-
-    Range e1@(C w1 s1 _) e2@(C w2 s2 _) ->
-        do (a1,c1,t1) <- gen e1
-           (a2,c2,t2) <- gen e2
-           return ( unionsA [a1,a2]
-                  , Set.unions [ c1, c2, Set.fromList [ C w1 s1 (t1 :=: int)
-                                                      , C w1 s2 (t2 :=: int) ] ]
-                  , listOf int )
-
-    MultiIf ps -> do (ass,css,t:ts) <- unzip3 `liftM` mapM genPair ps
-                     let cs = Set.fromList (map (ctx' . (t :=:)) ts)
-                     return (unionsA ass, Set.unions (cs:css), t)
-        where genPair (b@(C t s _),e) = do 
-                (a1,c1,t1) <- gen b
-                (a2,c2,t2) <- gen e
-                return ( unionsA [a1,a2]
-                       , Set.unions [ c1, c2
-                                    , Set.singleton (C t s (t1 :=: bool)) ]
-                       , t2 )
-
-    IntNum _ -> do t <- beta
-                   return (Map.empty, Set.singleton (ctx' $ t :<: number), t)
-
-    FloatNum _ -> primitive float
-    Chr _ -> primitive char
-    Str _ -> primitive string
-    Boolean _ -> primitive bool
-    Markdown _ -> primitive element
-
-
-primitive :: Type -> GuidCounter (TVarMap, ConstraintSet, Type)
-primitive t = return (Map.empty, Set.empty, t)
-
-caseGen :: Type
-        -> (Pattern, CExpr)
-        -> GuidCounter (TVarMap, ConstraintSet, Type)
-caseGen tipe (p, ce@(C _ span e)) = do
-  (as ,cs ,t) <- gen ce
-  (as',cs',_) <- patternGen (ctx p span) tipe as p
-  return ( as', Set.union cs cs', t )
-
-patternGen :: (Constraint -> Context Constraint)
-           -> Type     -- Type of e in `case e of ...`
-           -> TVarMap
-           -> Pattern
-           -> GuidCounter (TVarMap, ConstraintSet, Type)
-patternGen ctxt tipe as pattern =
-  case pattern of
-    PAnything -> do b <- beta ; return ( as, Set.empty, b )
-    PVar v -> do
-      b <- beta
-      let cs = map (ctxt . (b :=:) . VarT) (Map.findWithDefault [] v as)
-      return ( Map.delete v as, Set.fromList (ctxt (b :=: tipe) : cs), b )
-    PData name ps -> do
-      constr <- guid
-      output <- beta
-      let step (as,cs,tipe) p = do b <- beta
-                                   (as',cs',t) <- patternGen ctxt b as p
-                                   return (as', Set.union cs cs', t ==> tipe)
-      (as',cs, t) <- foldM step (as,Set.empty,tipe) (reverse ps)
-      return ( Map.insert name [constr] as'
-             , Set.insert (ctxt (VarT constr :=: t)) cs
-             , output )
-    PRecord fs ->
-        do pairs <- mapM (\f -> do b <- beta; return (f,b)) fs
-           b <- beta
-           let t = RecordT (Map.fromList $ map (second (:[])) pairs) b
-               mkCs (name,tipe) = map (ctxt . (tipe :=:) . VarT)
-                                  (Map.findWithDefault [] name as)
-           return ( foldr Map.delete as fs
-                  , Set.fromList (ctxt (t :=: tipe) : concatMap mkCs pairs)
-                  , t )
-
-
-defScheme :: Def -> GuidCounter (Map.Map String [X], Scheme)
-defScheme def = do (as,cs,hint) <- defGen def
-                   return ( as, snd hint )
-
-defGen def = case def of
-               FnDef f args e   -> defGenHelp f args e
-               OpDef op a1 a2 e -> defGenHelp op [a1,a2] e
-
-defGenHelp 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 -> ctx arg NoSpan $ VarT x :=: VarT y) as'
-  cs' <- concat `liftM` mapM genCs argDict
-  scheme <- Subs.generalize (concat $ Map.elems as') $
-            Forall (map snd argDict) (cs' ++ Set.toList cs) tipe
-  return ( as', Set.empty, (name, scheme) )
-
-
-stmtGen :: Statement
-        -> GuidCounter (TVarMap, ConstraintSet, Map.Map String Scheme)
-stmtGen stmt =
-  case stmt of
-    Definition def -> do (as,cs,hint) <- defGen def
-                         return ( as, cs, uncurry Map.singleton hint )
-
-    Datatype name xs tcs ->
-        let toScheme ts = Forall xs [] (foldr (==>) (ADT name $ map VarT xs) ts)
-        in  return (Map.empty, Set.empty, Map.fromList (map (second toScheme) tcs))
-
-    ExportEvent js elm tipe ->
-        do x <- guid
-           return ( Map.singleton elm [x]
-                  , Set.singleton . ctx elm NoSpan $ VarT x :=: tipe
-                  , Map.empty )
-
-    ImportEvent js e@(C txt span base) elm tipe ->
-        do (as,cs,t) <- gen e
-           return ( as
-                  , Set.insert (C txt span (signalOf t :=: tipe)) cs
-                  , Map.singleton elm (Forall [] [] tipe) )
-
-    TypeAnnotation name tipe ->
-        do schm <- Subs.generalize [] =<< Subs.superize name tipe
-           return (Map.empty, Set.empty, Map.singleton name schm)
-
-    TypeAlias _ _ _ -> return (Map.empty, Set.empty, Map.empty)
diff --git a/compiler/Types/Hints.hs b/compiler/Types/Hints.hs
deleted file mode 100644
--- a/compiler/Types/Hints.hs
+++ /dev/null
@@ -1,31 +0,0 @@
-module Types.Hints (hints) where
-
-import Control.Arrow (first)
-import Control.Monad (liftM)
-import Data.Maybe (catMaybes)
-import qualified Data.Map as Map
-import Guid
-import qualified Libraries as Libs
-import Parse.Library (iParse)
-import Parse.Types
-import qualified Types.Substitutions as Subs
-import Types.Types
-
-hints :: GuidCounter [(String, Scheme)]
-hints = liftM catMaybes (mapM toScheme values)
- where
-  values :: [(String, String)]
-  values = addPrefixes (Map.toList (Map.map Map.toList Libs.libraries))
-
-  addPrefixes :: [(String,[(String, String)])] -> [(String, String)]
-  addPrefixes = concatMap (\(m,vs) -> map (first (\n -> m ++ "." ++ n)) vs)
-
-  toScheme :: (String, String) -> GuidCounter (Maybe (String, Scheme))
-  toScheme (name, 't':'y':'p':'e':' ':_) = return Nothing
-  toScheme (name, 'd':'a':'t':'a':' ':_) = return Nothing
-  toScheme (name, tipeString) =
-    let err = "compiler error parsing type of " ++ name ++ ":\n" ++ tipeString in
-    case iParse (fmap toType typeExpr) err tipeString of
-      Left err   -> error (show err)
-      Right tipe -> do scheme <- Subs.generalize [] =<< Subs.superize name tipe
-                       return (Just (name, scheme))
diff --git a/compiler/Types/Solver.hs b/compiler/Types/Solver.hs
deleted file mode 100644
--- a/compiler/Types/Solver.hs
+++ /dev/null
@@ -1,211 +0,0 @@
-
-module Types.Solver (solver) where
-
-import Context
-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
-import Types.Alias (dealias)
-
-isSolved ss (C _ _ (t1 :=: t2)) = t1 == t2
-isSolved ss (C _ _ (x :<<: _)) = isJust (lookup x ss)
-isSolved ss c = False
-
-type Aliases = Map.Map String ([X],Type)
-
-crush :: Aliases -> Scheme -> GuidCounter (Either String Scheme)
-crush aliases (Forall xs cs t) =
-    do subs <- solver aliases Map.empty cs
-       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 txt span x s t1 rltn t2 = do
-  (t1',cs1) <- sub t1
-  (t2',cs2) <- sub t2
-  return (C txt span (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 aliases x s c =
-    do s' <- crush aliases s
-       case s' of
-         Right s'' -> Right `liftM` schemeSub' x s'' c
-         Left err  -> return $ Left err
-
-schemeSub' x s c@(C txt span constraint) =
-  case constraint of
-    (t1 :=: t2) -> schemeSubHelp txt span x s t1 (:=:) t2
-    (t1 :<: t2) -> schemeSubHelp txt span x s t1 (:<:) t2
-    (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 [ C txt span c' ]
-
-recordConstraints eq fs t fs' t' =
-  liftM concat . sequence $
-      [ constrain fs fs'
-      , liftM concat . mapM (\(k,ts) -> zipper [] k ts []) . Map.toList $
-              Map.difference fs fs'
-      , liftM concat . mapM (\(k,ts) -> zipper [] k [] ts) . Map.toList $
-              Map.difference fs' fs
-      ]
-    where constrain :: Map.Map String [Type] -> Map.Map String [Type]
-                    -> GuidCounter [Context Constraint]
-          constrain as bs = liftM concat . sequence . Map.elems $
-                            Map.intersectionWithKey (zipper []) as bs
-          zipper :: [Context Constraint] -> String -> [Type] -> [Type]
-                 -> GuidCounter [Context Constraint]
-          zipper cs k xs ys =
-            case (xs,ys) of
-              (a:as, b:bs) -> zipper (eq a b : cs) k as bs
-              ([],[]) -> return cs
-              (as,[]) -> do x <- guid
-                            let tipe = RecordT (Map.singleton k as) (VarT x)
-                            return (cs ++ [eq t' tipe])
-              ([],bs) -> do x <- guid
-                            let tipe = RecordT (Map.singleton k bs) (VarT x)
-                            return (cs ++ [eq t tipe])
-                              
-solver :: Aliases
-       -> Map.Map X Type
-       -> [Context Constraint]
-       -> GuidCounter (Either String (Map.Map X Type))
-solver _ subs [] = return $ Right subs
-solver aliases subs (C txt span c : cs) =
-  let ctx = C txt span
-      eq t1 t2 = ctx (t1 :=: t2)
-      solv = solver aliases subs
-      uniError' = uniError (\t1 t2 -> solv (eq t1 t2 : cs)) aliases txt span
-  in case c of
-      -- Destruct Type-constructors
-      t1@(ADT n1 ts1) :=: t2@(ADT n2 ts2) ->
-          if n1 == n2 then solv (zipWith eq ts1 ts2 ++ cs)
-                      else uniError' t1 t2
-
-      LambdaT t1 t2 :=: LambdaT t1' t2' ->
-          solv ([ eq t1 t1', eq t2 t2' ] ++ cs)
-
-      RecordT fs t :=: RecordT fs' t' ->
-          do cs' <- recordConstraints eq fs t fs' t'
-             solv (cs' ++ cs)
-
-      -- Type-equality
-      VarT x :=: VarT y
-          | x == y    -> solv cs
-          | 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 txt span xts yts
-                          [t] -> let cs1 = subst [(x,t),(y,t)] cs in
-                                 cs1 `seq` solver aliases (setXY t subs) cs1
-                          _   -> solver aliases (setXY (Super ts) subs) cs
-                (Just (Super xts), _) ->
-                    let cs2 = subst [(y,VarT x)] cs in
-                    solver aliases (Map.insert y (VarT x) subs) cs2
-                (_, _) ->
-                    let cs3 = subst [(x,VarT y)] cs in
-                    solver aliases (Map.insert x (VarT y) subs) cs3
-
-      VarT x :=: t -> do
-          if x `occurs` t then occursError txt span (VarT x) t else
-            (case Map.lookup x subs of
-               Nothing ->
-                   let cs4 = subst [(x,t)] cs
-                       subs' = Map.map (subst [(x,t)]) $ Map.insert x t subs
-                   in  solver aliases subs' cs4
-               Just (Super ts) ->
-                   let ts' = Set.intersection ts (Set.singleton t) in
-                   case Set.toList ts' of
-                     []   -> solv (ctx (t :<: Super ts) : cs)
-                     [t'] -> let cs5 = subst [(x,t)] cs in
-                             solver aliases (Map.insert x t' subs) cs5
-                     _    -> solver aliases (Map.insert x (Super ts') subs) cs
-               Just t' -> solv (ctx (t' :=: t) : cs)
-            )
-
-      t :=: VarT x -> solv ((ctx (VarT x :=: t)) : cs)
-
-      t1 :=: t2 | t1 == t2  -> solv cs
-                | otherwise -> uniError' t1 t2
-
-      -- subtypes
-      VarT x :<: Super ts ->
-          case Map.lookup x subs of
-            Nothing -> solver aliases (Map.insert x (Super ts) subs) cs
-            Just (Super ts') ->
-                case Set.toList $ Set.intersection ts ts' of
-                  []   -> unionError txt span ts ts'
-                  [t]  -> solver aliases (Map.insert x t subs) (subst [(x,t)] cs)
-                  ts'' -> solver aliases subs' cs
-                    where subs' = Map.insert x (Super $ Set.fromList ts'') subs
-
-      ADT "List" [t] :<: Super ts
-          | any f (Set.toList ts) -> solv cs
-          | otherwise -> subtypeError txt span (ADT "List" [t]) (Super ts)
-                 where f (ADT "List" [VarT _]) = True
-                       f (ADT "List" [t']) = dealias aliases t == t'
-                       f _ = False
-
-      t :<: Super ts
-          | Set.member t ts -> solv cs
-          | Set.member (dealias aliases t) ts -> solv cs
-          | otherwise -> subtypeError txt span t (Super ts)
-
-      x :<<: s
-          | any (occurs x) cs ->
-              do css <- mapM (schemeSub aliases x s) cs
-                 case lefts css of
-                   err : _ -> return $ Left err
-                   [] -> solv (concat (rights css))
-          | otherwise ->
-              do (t,cs7) <- concretize s
-                 solv (cs ++ ctx (VarT x :=: t) : cs7)
-
-showMsg msg = case msg of
-                Just str -> "\nIn context: " ++ str
-                Nothing  -> ""
-
-occursError msg span t1 t2 =
-    return . Left $ concat
-        [ "Type error (" ++ show span ++ "):\n"
-        , "Occurs check: cannot construct the infinite type:\n"
-        , show t1, " = ", show t2, showMsg msg ]
-
-uniError solveWith aliases msg span t1 t2 =
-    let t1' = dealias aliases t1
-        t2' = dealias aliases t2
-    in  if t1 /= t1' || t2 /= t2'
-        then solveWith t1' t2'
-        else return . Left $ concat
-                 [ "Type error (" ++ show span ++ "):\n"
-                 , show t1, " is not equal to ", show t2, showMsg msg ]
-
-unionError msg span ts ts' =
-    return . Left $ concat
-        [ "Type error (" ++ show span ++ "):\n"
-        , "There are no types in both "
-        , show (Super ts), " and ", show (Super ts'), showMsg msg ]
-
-subtypeError msg span t s =
-    return . Left $ concat
-        [ "Type error (" ++ show span ++ "):\n"
-        , show t, " is not a ", show s, showMsg msg ]
-
diff --git a/compiler/Types/Substitutions.hs b/compiler/Types/Substitutions.hs
deleted file mode 100644
--- a/compiler/Types/Substitutions.hs
+++ /dev/null
@@ -1,136 +0,0 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-module Types.Substitutions (subst,
-                            occurs,
-                            freeVars,
-                            concretize,
-                            rescheme,
-                            generalize,
-                            superize) where
-
-import Ast
-import Context
-import Control.Monad (liftM, liftM2)
-import Control.Monad.State (runState, State, get, put)
-import Data.List (nub)
-import qualified Data.Set as Set
-import qualified Data.Map as Map
-import Guid
-import Types.Types
-
-class Subst a where
-  subst :: [(X,Type)] -> a -> a
-
-instance Subst Type where
- subst ss t =
-  case t of
-   VarT x -> case lookup x ss of
-               Nothing        -> VarT x
-               Just (Super _) -> VarT x
-               Just t         -> t
-   LambdaT t1 t2 -> LambdaT (subst ss t1) (subst ss t2)
-   ADT name ts -> ADT name (subst ss ts)
-   RecordT fs t -> RecordT (Map.map (subst ss) fs) (subst ss t)
-   EmptyRecord -> EmptyRecord
-   Super ts -> Super ts
-
-instance Subst Scheme where
-  subst ss (Forall vs cs t) = Forall vs (subst ss cs) (subst ss t)
-
-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
-
-instance Subst a => Subst (Context a) where
-  subst ss (C str span c) = C str span (subst ss c)
-
-instance Subst a => Subst [a] where
-  subst ss as = map (subst ss) as
-
-
-class FreeVars a where
-  freeVars :: a -> [X]
-
-instance FreeVars Type where
-  freeVars t =
-    case t of
-      VarT v        -> [v]
-      LambdaT t1 t2 -> freeVars t1 ++ freeVars t2
-      ADT _ ts      -> concatMap freeVars ts
-      RecordT fs t  -> freeVars (concat $ Map.elems fs) ++ freeVars t
-      EmptyRecord   -> []
-      Super _       -> []
-
-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
-
-instance FreeVars a => FreeVars (Context a) where
-  freeVars (C _ _ c) = freeVars c    
-
-instance FreeVars a => FreeVars [a] where
-  freeVars = concatMap freeVars
-
-occurs x t = x `elem` freeVars t
-
-concretize :: Scheme -> GuidCounter (Type, [Context Constraint])
-concretize (Forall xs cs t) = do
-  ss <- zip xs `liftM` mapM (\_ -> liftM VarT guid) xs
-  return (subst ss t, subst ss cs)
-
-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 freeVars cs
-          frees = Set.toList $ Set.difference allFrees (Set.fromList exceptions)
-
-newtype Superize a = S { runSuper :: State ([X], [X], [X]) a }
-    deriving (Monad)
-
-superize :: String -> Type -> GuidCounter Scheme
-superize name tipe =
-    do constraints <- liftM concat $
-                      sequence [ mapM (<: nmbr) (nub ns)
-                               , mapM (<: apnd) (nub as)
-                               , mapM (<: comp) (nub cs) ]
-       return (Forall (concat [ns,as,cs]) constraints tipe')
- where
-  (tipe', (ns,as,cs)) = runState (runSuper (go tipe)) ([],[],[])
-  t <: super = do x <- guid
-                  return $ C (Just name) NoSpan (VarT t :<: super x)
-
-  nmbr t = number
-  apnd t = appendable t
-  comp t = comparable t
-
-  go :: Type -> Superize Type
-  go t =
-    case t of
-      EmptyRecord -> return t
-      Super _     -> return t
-      VarT _      -> return t
-      LambdaT t1 t2        -> liftM2 LambdaT (go t1) (go t2)
-      ADT "Number" [VarT t] -> addNumber t
-      ADT "Appendable" [VarT t] -> addAppendable t
-      ADT "Comparable" [VarT t] -> addComparable t
-      ADT name ts          -> liftM (ADT name) (mapM go ts)
-      RecordT fs t         -> liftM2 RecordT fs' (go t)
-          where pairs = Map.toList fs
-                fs' = do ps <- mapM (\(f,t) -> liftM ((,) f) (mapM go t)) pairs
-                         return (Map.fromList ps)
-
-  add :: (X -> ([X],[X],[X]) -> ([X],[X],[X])) -> X -> Superize Type
-  add f v = S $ do (ns, as, cs) <- get
-                   put $ f v (ns, as, cs)
-                   return (VarT v)
-
-  addNumber     = add (\n (ns,as,cs) -> (n:ns,as,cs))
-  addAppendable = add (\a (ns,as,cs) -> (ns,a:as,cs))
-  addComparable = add (\c (ns,as,cs) -> (ns,as,c:cs))
diff --git a/compiler/Types/Types.hs b/compiler/Types/Types.hs
deleted file mode 100644
--- a/compiler/Types/Types.hs
+++ /dev/null
@@ -1,94 +0,0 @@
-
-module Types.Types where
-
-import Context
-import Data.Char (isDigit)
-import Data.List (intercalate,isPrefixOf)
-import qualified Data.Set as Set
-import qualified Data.Map as Map
-
-type X = Int
-
-data Type = LambdaT Type Type
-          | VarT X
-          | ADT String [Type]
-          | EmptyRecord
-          | RecordT (Map.Map String [Type]) Type
-          | Super (Set.Set Type)
-            deriving (Eq, Ord)
-
-data Scheme = Forall [X] [Context Constraint] Type deriving (Eq, Ord, Show)
-
-data Constraint = Type :=: Type
-                | Type :<: Type
-                | X :<<: Scheme
-                  deriving (Eq, Ord, Show)
-
-recordT :: [(String,Type)] -> Map.Map String [Type]
-recordT fields =
-    foldl (\r (x,t) -> Map.insertWith (++) x [t] r) Map.empty fields
-
-recordOf :: [(String,Type)] -> Type
-recordOf fields = RecordT (recordT fields) EmptyRecord
-
-tipe t = ADT t []
-
-int = tipe "Int"
-float = tipe "Float"
-time = tipe "Time"
-date = tipe "Date"
-
-char = tipe "Char"
-bool = tipe "Bool"
-text = tipe "Text"
-order = tipe "Order"
-string = tipe "String"
-
-number = Super $ Set.fromList [ int, float, time ]
-appendable t = Super $ Set.fromList [ string, text, listOf (VarT t) ]
-comparable t = Super $ Set.fromList [ int, float, char, string, time, date ]
-
-element   = tipe "Element"
-
-listOf t   = ADT "List" [t]
-signalOf t = ADT "Signal" [t]
-tupleOf ts = ADT ("Tuple" ++ show (length ts)) ts
-maybeOf t  = ADT "Maybe" [t]
-eitherOf a b = ADT "Either" [a,b]
-pairOf t = tupleOf [t,t]
-point = pairOf int
-
-infixr ==>
-t1 ==> t2 = LambdaT t1 t2
-
-infix 8 -:
-name -: tipe = (,) name $ Forall [] [] tipe
-
-parens = ("("++) . (++")")
-
-instance Show Type where
-  show t =
-   let addParens (c:cs) =
-           if notElem ' ' cs || c == '(' then c:cs else parens (c:cs)
-   in 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 name ++ concatMap ((' ':) . addParens . show) cs
-      Super ts -> "{" ++ (intercalate "," . map show $ Set.toList ts) ++ "}"
-      EmptyRecord -> "{}"
-      RecordT fs t ->
-        start ++ intercalate ", " (concatMap fields $ Map.toList fs) ++ " }"
-           where field n s = n ++ " : " ++ show s
-                 fields (n,ss) = map (field n) ss
-                 start = case t of
-                           EmptyRecord -> "{ "
-                           _ -> "{ " ++ show t ++ " | "
-
-
-isTupleString str = "Tuple" `isPrefixOf` str && all isDigit (drop 5 str)
diff --git a/compiler/Types/Unify.hs b/compiler/Types/Unify.hs
deleted file mode 100644
--- a/compiler/Types/Unify.hs
+++ /dev/null
@@ -1,16 +0,0 @@
-
-module Types.Unify (unify) where
-
-import Control.Monad (liftM)
-import qualified Data.Map as Map
-
-import Ast
-import Guid
-import Types.Constrain
-import Types.Solver
-import Types.Alias as Alias
-
-unify hints modul@(Module _ _ _ stmts) = run $ do
-  constraints <- constrain hints modul
-  either (return . Left) (solver (Alias.get stmts) Map.empty) constraints
-
diff --git a/compiler/Unique.hs b/compiler/Unique.hs
new file mode 100644
--- /dev/null
+++ b/compiler/Unique.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module Unique (guid, set, run, runAt, Unique) where
+
+import Control.Monad.State (evalState, State, get, put)
+
+-- Wrapper around State monad.
+newtype Unique a = U { runU :: State Int a }
+    deriving (Monad)
+
+-- Get the next GUID, incrementing the counter.
+guid :: Unique Int
+guid = U $ do n <- get
+              put (n + 1)
+              return n
+
+set n = U (put n)
+
+run = runAt 0
+runAt n x = evalState (runU x) n
diff --git a/data/elm-runtime.js b/data/elm-runtime.js
new file mode 100644
--- /dev/null
+++ b/data/elm-runtime.js
@@ -0,0 +1,5758 @@
+Elm = {}; Elm.Native = {}; Elm.Native.Graphics = {};
+Elm.Graphics = {}; ElmRuntime = {}; ElmRuntime.Render = {};
+Elm = {}; Elm.Native = {}; Elm.Native.Graphics = {};
+Elm.Graphics = {}; ElmRuntime = {}; ElmRuntime.Render = {}
+
+Elm.Native.Basics = function(elm) {
+  'use strict';
+  if (elm.Native.Basics) return elm.Native.Basics;
+
+  var JS = Elm.Native.JavaScript(elm);
+  // var Maybe = Elm.Maybe(elm);
+  var Utils = Elm.Native.Utils(elm);
+  //var Char = Elm.Char(elm);
+
+  function div(a,b) { return (a/b)|0; }
+  function rem(a,b) { return a % b; }
+  var mod = Utils.mod;
+  function abs(x) { return x < 0 ? -x : x; }
+  function logBase(base,n) { return Math.log(n) / Math.log(base); }
+  function min(a,b) { return Utils.cmp(a,b) < 0 ? a : b; }
+  function max(a,b) { return Utils.cmp(a,b) > 0 ? a : b; }
+  function clamp(lo,hi,n) {
+      return Utils.cmp(n,lo) < 0 ? lo : Utils.cmp(n,hi) > 0 ? hi : n; }
+  function xor(a,b) { return a !== b; }
+  function not(b) { return !b; }
+
+  function truncate(n) { return n|0; }
+
+  function curry(f,a,b) { return f(Utils.Tuple2(a,b)); }
+  function uncurry(f,v) { return A2(f,v._0,v._1); }
+  function fst(t) { return t._0; }
+  function snd(t) { return t._1; }
+/*
+  function readInt(str) {
+    var s = JS.fromString(str);
+    var len = s.length;
+    if (len === 0) { return Maybe.Nothing; }
+    var start = 0;
+    if (s[0] == '-') {
+      if (len === 1) { return Maybe.Nothing; }
+      start = 1;
+    }
+    for (var i = start; i < len; ++i) {
+      if (!Char.isDigit(s[i])) { return Maybe.Nothing; }
+    }
+    return Maybe.Just(parseInt(s, 10));
+  }
+
+  function readFloat(str) {
+    var s = JS.fromString(str);
+    var len = s.length;
+    if (len === 0) { return Maybe.Nothing; }
+    var start = 0;
+    if (s[0] == '-') {
+      if (len === 1) { return Maybe.Nothing; }
+      start = 1;
+    }
+    var dotCount = 0;
+    for (var i = start; i < len; ++i) {
+      if (Char.isDigit(s[i])) { continue; }
+      if (s[i] === '.') {
+        dotCount += 1;
+        if (dotCount <= 1) { continue; }
+      }
+      return Maybe.Nothing;
+    }
+    return Maybe.Just(parseFloat(s));
+  }
+*/
+  var basics = {
+      div:F2(div),
+      rem:F2(rem),
+      mod:mod,
+
+      pi:Math.PI,
+      e:Math.e,
+      cos:Math.cos,
+      sin:Math.sin,
+      tan:Math.tan,
+      acos:Math.acos,
+      asin:Math.asin,
+      atan:Math.atan,
+      atan2:F2(Math.atan2),
+
+      sqrt:Math.sqrt,
+      abs:abs,
+      logBase:F2(logBase),
+      min:F2(min),
+      max:F2(max),
+      clamp:F3(clamp),
+      compare:Utils.compare,
+
+      xor:F2(xor),
+      not:not,
+
+      truncate:truncate,
+      ceiling:Math.ceil,
+      floor:Math.floor,
+      round:Math.round,
+      toFloat:function(x) { return x; },
+
+      //readInt:readInt,
+      //readFloat:readFloat,
+
+      curry:F3(curry),
+      uncurry:F2(uncurry),
+      fst:fst,
+      snd:snd
+  };
+
+  return elm.Native.Basics = basics;
+};
+
+Elm.Native.Char = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Char) return elm.Native.Char;
+
+ function isBetween(lo,hi) { return function(chr) {
+	 var c = chr.charCodeAt(0);
+	 return lo <= c && c <= hi;
+     };
+ }
+ var isDigit = isBetween('0'.charCodeAt(0),'9'.charCodeAt(0));
+ var chk1 = isBetween('a'.charCodeAt(0),'f'.charCodeAt(0));
+ var chk2 = isBetween('A'.charCodeAt(0),'F'.charCodeAt(0));
+
+ return elm.Native.Char = {
+     fromCode : function(c) { return String.fromCharCode(c); },
+     toCode   : function(c) { return c.charCodeAt(0); },
+     toUpper  : function(c) { return c.toUpperCase(); },
+     toLower  : function(c) { return c.toLowerCase(); },
+     toLocaleUpper : function(c) { return c.toLocaleUpperCase(); },
+     toLocaleLower : function(c) { return c.toLocaleLowerCase(); },
+     isLower    : isBetween('a'.charCodeAt(0),'z'.charCodeAt(0)),
+     isUpper    : isBetween('A'.charCodeAt(0),'Z'.charCodeAt(0)),
+     isDigit    : isDigit,
+     isOctDigit : isBetween('0'.charCodeAt(0),'7'.charCodeAt(0)),
+     isHexDigit : function(c) { return isDigit(c) || chk1(c) || chk2(c); }
+ };
+
+};
+
+
+Elm.Native.Color = function(elm) {
+ "use strict";
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Color) return elm.Native.Color;
+
+ var Utils = Elm.Native.Utils(elm);
+
+ function complement(rgb) {
+     var hsv = toHSV(rgb);
+     hsv.hue = (hsv.hue + 180) % 360;
+     return toRGB(hsv);
+ }
+
+ function hsva(h,s,v,a) {
+     var degree = A2(Utils.mod, h * 180 / Math.PI, 360);
+     var clr = toRGB({hue:degree, saturation:s, value:v});
+     clr._3 = a;
+     return clr;
+ }
+
+ function hsv(h,s,v) {
+     var degree = A2(Utils.mod, h * 180 / Math.PI, 360);
+     return toRGB({hue:degree, saturation:s, value:v});
+ }
+
+ function toHSV(rgb) {
+  var hsv = {};
+  var r = rgb._0 / 255.0, g = rgb._1 / 255.0, b = rgb._2 / 255.0;
+  var M = Math.max(r,g,b);
+  var m = Math.min(r,g,b);
+  var c = M - m;
+
+  var h = 0;
+       if (c === 0) { h = 0; }
+  else if (M === r) { h = ((g - b) / c) % 6; }
+  else if (M === g) { h = ((b - r) / c) + 2; }
+  else if (M === b) { h = ((r - g) / c) + 4; }
+  h *= 60;
+
+  return { value : M, hue : h, saturation : (M === 0 ? 0 : c / M) };
+ }
+
+ function between(lo,hi,x) { return lo <= x && x < hi; }
+ function norm(n) { return Math.round(n*255); }
+
+ function toRGB(hsv) {
+  var c = hsv.value * hsv.saturation;
+  var hue = hsv.hue / 60;
+  var x = c * (1 - Math.abs((hue % 2) - 1));
+  var r = 0, g = 0, b = 0;
+       if (between(0,1,hue)) { r = c; g = x; b = 0; }
+  else if (between(1,2,hue)) { r = x; g = c; b = 0; }
+  else if (between(2,3,hue)) { r = 0; g = c; b = x; }
+  else if (between(3,4,hue)) { r = 0; g = x; b = c; }
+  else if (between(4,5,hue)) { r = x; g = 0; b = c; }
+  else if (between(5,6,hue)) { r = c; g = 0; b = x; }
+
+  var m = hsv.value - c;
+  return { ctor:"Color", _0:norm(r+m), _1:norm(g+m), _2:norm(b+m), _3:1 };
+ }
+
+ return elm.Native.Color = {
+    hsva:F4(hsva),
+    hsv:F3(hsv),
+    complement:complement
+ };
+
+};
+Elm.Native.Date = function(elm) {
+ 'use strict';
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Date) return elm.Native.Date;
+
+ var JS = Elm.JavaScript(elm);
+ var Maybe = Elm.Maybe(elm);
+
+ function dateNow() { return new window.Date; }
+ function readDate(str) {
+     var d = new window.Date(JS.fromString(str));
+     if (isNaN(d.getTime())) return Maybe.Nothing;
+     return Maybe.Just(d);
+ }
+
+ var dayTable = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
+ var monthTable = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
+		   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; 
+
+ return elm.Native.Date = {
+     read    : readDate,
+     year    : function(d) { return d.getFullYear(); },
+     month   : function(d) { return { ctor:monthTable[d.getMonth()] }; },
+     day     : function(d) { return d.getDate(); },
+     hour    : function(d) { return d.getHours(); },
+     minute  : function(d) { return d.getMinutes(); },
+     second  : function(d) { return d.getSeconds(); },
+     toTime  : function(d) { return d.getTime(); },
+     dayOfWeek : function(d) { return { ctor:dayTable[d.getDay()] }; }
+ };
+
+};
+
+Elm.Native.Error = function(elm) {
+    'use strict';
+    elm.Native = elm.Native || {};
+    if (elm.Native.Error) return elm.Native.Error;
+
+    var fromString = Elm.Native.JavaScript(elm).fromString;
+
+    function indent(lines) {
+        var msg = '';
+        for (var i = 0; i < lines.length; ++i) {
+            msg += '<br/>&nbsp; &nbsp; ' + lines[i];
+        }
+        return msg;
+    }
+
+    function Case(moduleName, span) { 
+	var msg = indent(['Non-exhaustive pattern match in case-expression.',
+                          'Make sure your patterns cover every case!']);
+	throw new Error('Runtime error in module ' + moduleName + ' (' + span + '):' + msg);
+    }
+
+    function If(moduleName, span) { 
+	var msg = indent(['Non-exhaustive pattern match in multi-way-if expression.',
+                          'It is best to use \'otherwise\' as the last branch of multi-way-if.']);
+	throw new Error('Runtime error in module ' + moduleName + ' (' + span + '):' + msg);
+    }
+
+    function raise(str) { throw new Error(fromString(str)); }
+
+    return elm.Native.Error = { Case: Case, If: If, raise: raise };
+};
+function F2(fun) {
+  function wrapper(a) { return function(b) { return fun(a,b) } }
+  wrapper.arity = 2;
+  wrapper.func = fun;
+  return wrapper;
+}
+
+function F3(fun) {
+  function wrapper(a) {
+    return function(b) { return function(c) { return fun(a,b,c) }}
+  }
+  wrapper.arity = 3;
+  wrapper.func = fun;
+  return wrapper;
+}
+
+function F4(fun) {
+  function wrapper(a) { return function(b) { return function(c) {
+    return function(d) { return fun(a,b,c,d) }}}
+  }
+  wrapper.arity = 4;
+  wrapper.func = fun;
+  return wrapper;
+}
+
+function F5(fun) {
+  function wrapper(a) { return function(b) { return function(c) {
+    return function(d) { return function(e) { return fun(a,b,c,d,e) }}}}
+  }
+  wrapper.arity = 5;
+  wrapper.func = fun;
+  return wrapper;
+}
+
+function F6(fun) {
+  function wrapper(a) { return function(b) { return function(c) {
+    return function(d) { return function(e) { return function(f) {
+      return fun(a,b,c,d,e,f) }}}}}
+  }
+  wrapper.arity = 6;
+  wrapper.func = fun;
+  return wrapper;
+}
+
+function F7(fun) {
+  function wrapper(a) { return function(b) { return function(c) {
+    return function(d) { return function(e) { return function(f) {
+      return function(g) { return fun(a,b,c,d,e,f,g) }}}}}}
+  }
+  wrapper.arity = 7;
+  wrapper.func = fun;
+  return wrapper;
+}
+
+function F8(fun) {
+  function wrapper(a) { return function(b) { return function(c) {
+    return function(d) { return function(e) { return function(f) {
+	return function(g) { return function(h) {return fun(a,b,c,d,e,f,g,h)}}}}}}}
+  }
+  wrapper.arity = 8;
+  wrapper.func = fun;
+  return wrapper;
+}
+
+function F9(fun) {
+  function wrapper(a) { return function(b) { return function(c) {
+    return function(d) { return function(e) { return function(f) {
+	return function(g) { return function(h) { return function(i) {
+        return fun(a,b,c,d,e,f,g,h,i) }}}}}}}}
+  }
+  wrapper.arity = 9;
+  wrapper.func = fun;
+  return wrapper;
+}
+
+function A2(fun,a,b) {
+  return fun.arity === 2 ? fun.func(a,b) : fun(a)(b);
+}
+function A3(fun,a,b,c) {
+  return fun.arity === 3 ? fun.func(a,b,c) : fun(a)(b)(c);
+}
+function A4(fun,a,b,c,d) {
+  return fun.arity === 4 ? fun.func(a,b,c,d) : fun(a)(b)(c)(d);
+}
+function A5(fun,a,b,c,d,e) {
+  return fun.arity === 5 ? fun.func(a,b,c,d,e) : fun(a)(b)(c)(d)(e);
+}
+function A6(fun,a,b,c,d,e,f) {
+  return fun.arity === 6 ? fun.func(a,b,c,d,e,f) : fun(a)(b)(c)(d)(e)(f);
+}
+function A7(fun,a,b,c,d,e,f,g) {
+  return fun.arity === 7 ? fun.func(a,b,c,d,e,f,g) : fun(a)(b)(c)(d)(e)(f)(g);
+}
+function A8(fun,a,b,c,d,e,f,g,h) {
+  return fun.arity === 8 ? fun.func(a,b,c,d,e,f,g,h) : fun(a)(b)(c)(d)(e)(f)(g)(h);
+}
+function A9(fun,a,b,c,d,e,f,g,h,i) {
+  return fun.arity === 9 ? fun.func(a,b,c,d,e,f,g,h,i)
+                         : fun(a)(b)(c)(d)(e)(f)(g)(h)(i);
+}
+
+Elm.Native.JavaScript = function(elm) {
+  'use strict';
+
+  elm.Native = elm.Native || {};
+  if (elm.Native.JavaScript) return elm.Native.JavaScript;
+
+  var List = Elm.Native.List(elm);
+  var Render = ElmRuntime.use(ElmRuntime.Render.Element);
+
+  function fromJS(v) {
+      var type = typeof v;
+      if (type === 'number' ) return v;
+      if (type === 'boolean') return v;
+      if (type === 'string' ) return List.fromArray(v);
+      if (v instanceof Array) {
+          var arr = [];
+          var len = v.length;
+          for (var i = 0; i < len; ++i) {
+              var x = fromJS(v[i]);
+              if (x !== null) arr.push(x);
+          }
+          return List.fromArray(arr);
+      }
+      if (type === 'object') {
+          var rec = { _:{} };
+          for (var f in v) {
+              var x = fromJS(v[f]);
+              if (x !== null) rec[f] = x;
+          }
+          return rec;
+      }
+      return null;
+  }
+
+  function toJS(v) {
+      var type = typeof v;
+      if (type === 'number' || type === 'boolean') return v;
+      if (type === 'object' && '_' in v) {
+          var obj = {};
+          for (var k in v) {
+              var x = toJS(v[k]);
+              if (x !== null) obj[k] = x;
+          }
+          return obj;
+      }
+      if (type === 'object' && (v.ctor === '::' || v.ctor === '[]')) {
+          var array = List.toArray(v);
+          if (typeof array[0] === 'string') {
+              array = array.join('');
+          } else {
+              for (var i = array.length; i--; ) {
+                  array[i] = toJS(array[i]);
+              }
+          }
+          return array;
+      }
+      return null;
+  }
+
+  function fromRecord(r) {
+      if (typeof r === 'object' && '_' in r) {
+          return toJS(r);
+      }
+      throw new Error("'fromRecord' must be called on a record.");
+  }
+
+  function id(n) { return n; }
+
+  function toElement(w,h,domNode) {
+      return A3( newElement, w, h, {
+              ctor: 'Custom',
+              type: 'DomNode',
+              render: function(node) { return node; },
+              update: function(node,oldNode,newNode) {
+                  if (node === newNode) return;
+                  node.parentNode.replaceChild(newNode, node);
+              },
+              model: domNode
+          });
+  }
+
+  function fromElement(element) {
+      return Render.render(element);
+  }
+
+  return elm.Native.JavaScript = {
+      toFloat    : id,
+      toBool     : id,
+      toInt      : function(n) { return n|0; },
+      toString   : List.fromArray,
+      toList     : List.fromArray,
+      fromString : function(s) { return List.toArray(s).join(''); },
+      fromList   : List.toArray,
+      fromInt    : id,
+      fromFloat  : id,
+      fromBool   : id,
+
+      toElement   : toElement,
+      fromElement : fromElement,
+      toRecord    : fromJS,
+      fromRecord  : fromRecord
+  };
+
+};
+
+Elm.Native.Json = function(elm) {
+  'use strict';
+
+  var Maybe = Elm.Maybe(elm);
+  var Dict = Elm.Dict(elm);
+  var List = Elm.List(elm);
+  var JS = Elm.JavaScript(elm);
+  var Utils = Elm.Native.Utils(elm);
+
+  function fromValue(v) {
+    switch (v.ctor) {
+    case 'Null'   : return null;
+    case 'String' : return JS.fromString(v._0);
+    case 'Object' :
+      var obj = {};
+      var array = JS.fromList(Dict.toList(v._0));
+      for (var i = array.length; i--; ) {
+	obj[JS.fromString(array[i]._0)] = fromValue(array[i]._1);
+      }
+      return obj;
+    case 'Array'  :
+      var array = JS.fromList(v._0);
+      for (var i = array.length; i--; ) {
+	array[i] = fromValue(array[i]);
+      }
+      return array;
+    default :
+      return v._0;
+    }
+  }
+
+  function toPrettyJSString(sep, obj) {
+    return JSON.stringify(fromValue(obj), null, JS.fromString(sep));
+  }
+
+  function toValue(v) {
+    switch (typeof v) {
+    case 'string' : return { ctor:"String", _0: JS.toString(v) };
+    case 'number' : return { ctor:"Number", _0: JS.toFloat(v)  };
+    case 'boolean': return { ctor:"Bool"  , _0: JS.toBool(v)   };
+    case 'object' :
+      if (v === null) return { ctor:"Null" };
+      if (v instanceof Array) {
+          for (var i = v.length; i--; ) { v[i] = toValue(v[i]); }
+	  return { ctor:"Array", _0: JS.toList(v) };
+      }
+      var array = [];
+      for (var k in v) array.push(Utils.Tuple2(JS.toString(k), toValue(v[k])));
+      return { ctor:"Object", _0: Dict.fromList(JS.toList(array)) };
+    }
+  }
+
+  function fromJSString(str) {
+    try {
+	return Maybe.Just(toValue(JSON.parse(str)));
+    } catch (e) {
+	return Maybe.Nothing;
+    }
+  }
+
+  return elm.Native.Json = {
+      toJSString : F2(toPrettyJSString),
+      fromJSString : fromJSString,
+      toJSObject : fromValue,
+      fromJSObject : toValue
+  };
+
+};
+Elm.Native.List = function(elm) {
+  "use strict";
+
+  elm.Native = elm.Native || {};
+  if (elm.Native.List) return elm.Native.List;
+  if ('values' in Elm.Native.List)
+      return elm.Native.List = Elm.Native.List.values;
+
+  var Utils = Elm.Native.Utils(elm);
+
+  // TODO: Improve Nil handling
+  // We can change places like:  if (xs.ctor === '[]') ... to if (xs === Nil) ...
+  // but only if we're confident Nil can only be defined once.
+  // Currently (27Mar2013) each module can have different instantiations, so multiple Nil objects can exist
+  // (and if they're used interchangeably then direct object comparison fails where ctor doesn't).
+  // So, this can only be fixed when modules initialisation is also fixed.
+  // The performance overhead of the .ctor calls is 5-10% according to jsperf (depending on fn + list size)
+  // (on firefox 19)
+
+  var Nil = { ctor:'[]' };
+
+  // using freeze for every cons would be nice but is a huge (9x on firefox 19)
+  // performance penalty
+  function Cons(hd,tl) { return { ctor:"::", _0:hd, _1:tl }; }
+
+  function throwError(f) {
+    throw new Error("Function '" + f + "' expects a non-empty list!");
+  }
+
+  function toArray(xs) {
+    var out = [];
+    while (xs.ctor !== '[]') {
+      out.push(xs._0);
+      xs = xs._1;
+    }
+    return out;
+  }
+
+  function fromArray(arr) {
+    var out = Nil;
+    for (var i = arr.length; i--; ) {
+      out = Cons(arr[i], out);
+    }
+    return out;
+  }
+
+  function range(lo,hi) {
+    var lst = Nil;
+    if (lo <= hi) {
+      do { lst = Cons(hi,lst) } while (hi-->lo);
+    }
+    return lst
+  }
+
+  function append(xs,ys) {
+    if (typeof xs === "string") { return xs.concat(ys); }
+    if (xs.ctor === '[]') { return ys; }
+    var root = Cons(xs._0, Nil);
+    var curr = root;
+    xs = xs._1;
+    while (xs.ctor !== '[]') {
+	curr._1 = Cons(xs._0, Nil);
+	xs = xs._1;
+	curr = curr._1;
+    }
+    curr._1 = ys;
+    return root;
+  }
+
+  function head(v) { return v.ctor === '[]' ? throwError('head') : v._0; }
+  function tail(v) { return v.ctor === '[]' ? throwError('tail') : v._1; }
+
+  function last(xs) {
+    if (xs.ctor === '[]') { throwError('last'); }
+    var out = xs._0;
+    while (xs.ctor !== '[]') {
+      out = xs._0;
+      xs = xs._1;
+    }
+    return out;
+  }
+
+  function map(f, xs) {
+    var arr = [];
+    while (xs.ctor !== '[]') {
+      arr.push(f(xs._0));
+      xs = xs._1;
+    }
+    return fromArray(arr);
+  }
+
+   // f defined similarly for both foldl and foldr (NB: different from Haskell)
+   // ie, foldl : (a -> b -> b) -> b -> [a] -> b
+  function foldl(f, b, xs) {
+    var acc = b;
+    while (xs.ctor !== '[]') {
+      acc = A2(f, xs._0, acc);
+      xs = xs._1;
+    }
+    return acc;
+  }
+
+  function foldr(f, b, xs) {
+    var arr = toArray(xs);
+    var acc = b;
+    for (var i = arr.length; i--; ) {
+      acc = A2(f, arr[i], acc);
+    }
+    return acc;
+  }
+
+  function foldl1(f, xs) {
+    return xs.ctor === '[]' ? throwError('foldl1') : foldl(f, xs._0, xs._1);
+  }
+
+  function foldr1(f, xs) {
+    if (xs.ctor === '[]') { throwError('foldr1'); }
+    var arr = toArray(xs);
+    var acc = arr.pop();
+    for (var i = arr.length; i--; ) {
+      acc = A2(f, arr[i], acc);
+    }
+    return acc;
+  }
+
+  function scanl(f, b, xs) {
+    var arr = toArray(xs);
+    arr.unshift(b);
+    var len = arr.length;
+    for (var i = 1; i < len; ++i) {
+      arr[i] = A2(f, arr[i], arr[i-1]);
+    }
+    return fromArray(arr);
+  }
+
+  function scanl1(f, xs) {
+    return xs.ctor === '[]' ? throwError('scanl1') : scanl(f, xs._0, xs._1);
+  }
+
+  function filter(pred, xs) {
+    var arr = [];
+    while (xs.ctor !== '[]') {
+      if (pred(xs._0)) { arr.push(xs._0); }
+      xs = xs._1;
+    }
+    return fromArray(arr);
+  }
+
+  function length(xs) {
+    var out = 0;
+    while (xs.ctor !== '[]') {
+      out += 1;
+      xs = xs._1;
+    }
+    return out;
+  }
+
+  function member(x, xs) {
+    while (xs.ctor !== '[]') {
+      if (Utils.eq(x,xs._0)) return true;
+      xs = xs._1;
+    }
+    return false;
+  }
+
+  function reverse(xs) { return fromArray(toArray(xs).reverse()); }
+
+  function concat(xss) {
+      if (xss.ctor === '[]') return xss;
+      var arr = toArray(xss);
+      var xs = arr[arr.length-1];
+      for (var i = arr.length-1; i--; ) {
+	  xs = append(arr[i], xs);
+      }
+      return xs;
+  }
+
+  function all(pred, xs) {
+    while (xs.ctor !== '[]') {
+      if (!pred(xs._0)) return false;
+      xs = xs._1;
+    }
+    return true;
+  }
+
+  function any(pred, xs) {
+    while (xs.ctor !== '[]') {
+      if (pred(xs._0)) return true;
+      xs = xs._1;
+    }
+    return false;
+  }
+
+  function zipWith(f, xs, ys) {
+    var arr = [];
+    while (xs.ctor !== '[]' && ys.ctor !== '[]') {
+      arr.push(A2(f, xs._0, ys._0));
+      xs = xs._1;
+      ys = ys._1;
+    }
+    return fromArray(arr);
+  }
+
+  function zip(xs, ys) {
+    var arr = [];
+    while (xs.ctor !== '[]' && ys.ctor !== '[]') {
+      arr.push(Utils.Tuple2(xs._0, ys._0));
+      xs = xs._1;
+      ys = ys._1;
+    }
+    return fromArray(arr);
+  }
+
+  function sort(xs) {
+    function cmp(a,b) {
+      var ord = Utils.compare(a,b).ctor;
+      return ord=== 'EQ' ? 0 : ord === 'LT' ? -1 : 1;
+    }
+    return fromArray(toArray(xs).sort(cmp));
+  }
+
+  function nth(xs, n) {
+    return toArray(xs)[n];
+  }
+
+  function take(n, xs) {
+    var arr = [];
+    while (xs.ctor !== '[]' && n > 0) {
+      arr.push(xs._0);
+      xs = xs._1;
+      --n;
+    }
+    return fromArray(arr);
+  }
+
+  function drop(n, xs) {
+    while (xs.ctor !== '[]' && n > 0) {
+      xs = xs._1;
+      --n;
+    }
+    return xs;
+  }
+
+  function join(sep, xss) {
+    if (typeof sep === 'string') return toArray(xss).join(sep);
+    if (xss.ctor === '[]') return Nil;
+    var s = toArray(sep);
+    var out = toArray(xss._0);
+    xss = xss._1;
+    while (xss.ctor !== '[]') {
+      out = out.concat(s, toArray(xss._0));
+      xss = xss._1;
+    }
+    return fromArray(out);
+  }
+
+  function split(seperator, list) {
+    var array = toArray(list);
+    var alen = array.length;
+    if (alen === 0) {
+      // splitting an empty list is a list of lists: [[]]
+      return Cons(Nil,Nil);
+    }
+
+    var sep = toArray(seperator);
+    var seplen = sep.length;
+    if (seplen === 0) {
+      // splitting with an empty sep is a list of all elements
+      // Same as (map (\x -> [x]) list)
+      var out = Nil;
+      for (var i = alen; i--; ) {
+        out = Cons(Cons(array[i],Nil), out);
+      }
+      return out;
+    }
+
+    var matches = [-seplen];
+    var sepStart = sep[0];
+    var len = alen - seplen + 1;
+    for (var i = 0; i < len; ++i) {
+      if (Utils.eq(array[i], sepStart)) {
+        var match = true;
+        for (var j = seplen; --j; ) {
+          if (!Utils.eq(array[i+j], sep[j])) { match = false;  break; }
+        }
+        if (match) {
+          matches.push(i);
+          i += seplen - 1;
+        }
+      }
+    }
+
+    // shortcut in case of no matches
+    if (matches.length === 0) {
+      return Cons(list,Nil);
+    }
+
+    var out = Nil;
+    var index = alen - 1;
+    for (var i = matches.length; i--; ) {
+      var temp = Nil;
+      var stop = matches[i] + seplen - 1;
+      for ( ; index > stop; --index ) {
+        temp = Cons(array[index], temp);
+      }
+      out = Cons(temp,out);
+      index -= seplen;
+    }
+    return out;
+  }
+
+  Elm.Native.List.values = {
+      Nil:Nil,
+      Cons:Cons,
+      cons:F2(Cons),
+      toArray:toArray,
+      fromArray:fromArray,
+      range:range,
+      append:append,
+
+      head:head,
+      tail:tail,
+      last:last,
+
+      map:F2(map),
+      foldl:F3(foldl),
+      foldr:F3(foldr),
+
+      foldl1:F2(foldl1),
+      foldr1:F2(foldr1),
+      scanl:F3(scanl),
+      scanl1:F2(scanl1),
+      filter:F2(filter),
+      length:length,
+      member:F2(member),
+      reverse:reverse,
+      concat:concat,
+
+      all:F2(all),
+      any:F2(any),
+      zipWith:F3(zipWith),
+      zip:F2(zip),
+      sort:sort,
+      nth:F2(nth),
+      take:F2(take),
+      drop:F2(drop),
+
+      join:F2(join),
+      split:F2(split)
+  };
+  return elm.Native.List = Elm.Native.List.values;
+
+};
+Elm.Native.Matrix2D = function(elm) {
+ "use strict";
+
+ elm.Native = elm.Native || {};
+ if (elm.Native.Matrix2D) return elm.Native.Matrix2D;
+
+ var A;
+ if (typeof Float32Array === 'undefined') {
+     A = function(arr) {
+         this.length = arr.length;
+         this[0] = arr[0];
+         this[1] = arr[1];
+         this[2] = arr[2];
+         this[3] = arr[3];
+         this[4] = arr[4];
+         this[5] = arr[5];
+     };
+ } else {
+     A = Float32Array;
+ }
+
+ // layout of matrix in an array is
+ //
+ //   | m11 m12 dx |
+ //   | m21 m22 dy |
+ //   |  0   0   1 |
+ //
+ //  new A([ m11, m12, dx, m21, m22, dy ])
+
+ var identity = new A([1,0,0,0,1,0]);
+ function matrix(m11, m12, m21, m22, dx, dy) {
+     return new A([m11, m12, dx, m21, m22, dy]);
+ }
+ function rotation(t) {
+     var c = Math.cos(t);
+     var s = Math.sin(t);
+     return new A([c, -s, 0, s, c, 0]);
+ }
+
+ function rotate(t,m) {
+     var c = Math.cos(t);
+     var s = Math.sin(t);
+     var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4];
+     return new A([m11*c + m12*s, -m11*s + m12*c, m[2],
+                   m21*c + m22*s, -m21*s + m22*c, m[5]]);
+ }
+ /*
+ function move(xy,m) {
+     var x = xy._0;
+     var y = xy._1;
+     var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4];
+     return new A([m11, m12, m11*x + m12*y + m[2],
+                   m21, m22, m21*x + m22*y + m[5]]);
+ }
+ function scale(s,m) { return new A([m[0]*s, m[1]*s, m[2], m[3]*s, m[4]*s, m[5]]); }
+ function scaleX(x,m) { return new A([m[0]*x, m[1], m[2], m[3]*x, m[4], m[5]]); }
+ function scaleY(y,m) { return new A([m[0], m[1]*y, m[2], m[3], m[4]*y, m[5]]); }
+ function reflectX(m) { return new A([-m[0], m[1], m[2], -m[3], m[4], m[5]]); }
+ function reflectY(m) { return new A([m[0], -m[1], m[2], m[3], -m[4], m[5]]); }
+
+ function transform(m11, m21, m12, m22, mdx, mdy, n) {
+     var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5];
+     return new A([m11*n11 + m12*n21,
+                   m11*n12 + m12*n22,
+                   m11*ndx + m12*ndy + mdx,
+                   m21*n11 + m22*n21,
+                   m21*n12 + m22*n22,
+                   m21*ndx + m22*ndy + mdy]);
+ }
+ */
+ function multiply(m, n) {
+     var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4], mdx = m[2], mdy = m[5];
+     var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5];
+     return new A([m11*n11 + m12*n21,
+                   m11*n12 + m12*n22,
+                   m11*ndx + m12*ndy + mdx,
+                   m21*n11 + m22*n21,
+                   m21*n12 + m22*n22,
+                   m21*ndx + m22*ndy + mdy]);
+ }
+
+ return elm.Native.Matrix2D = {
+     identity:identity,
+     matrix:F6(matrix),
+     rotation:rotation,
+     multiply:F2(multiply)
+     /*
+     transform:F7(transform),
+     rotate:F2(rotate),
+     move:F2(move),
+     scale:F2(scale),
+     scaleX:F2(scaleX),
+     scaleY:F2(scaleY),
+     reflectX:reflectX,
+     reflectY:reflectY
+     */
+ };
+
+};
+
+Elm.Native.Prelude = function(elm) {
+  'use strict';
+  if (elm.Native.Prelude) return elm.Native.Prelude;
+
+  var JS = Elm.Native.JavaScript(elm);
+  var Maybe = Elm.Maybe(elm);
+  var Char = Elm.Char(elm);
+
+  function readInt(str) {
+    var s = JS.fromString(str);
+    var len = s.length;
+    if (len === 0) { return Maybe.Nothing; }
+    var start = 0;
+    if (s[0] == '-') {
+      if (len === 1) { return Maybe.Nothing; }
+      start = 1;
+    }
+    for (var i = start; i < len; ++i) {
+      if (!Char.isDigit(s[i])) { return Maybe.Nothing; }
+    }
+    return Maybe.Just(parseInt(s, 10));
+  }
+
+  function readFloat(str) {
+    var s = JS.fromString(str);
+    var len = s.length;
+    if (len === 0) { return Maybe.Nothing; }
+    var start = 0;
+    if (s[0] == '-') {
+      if (len === 1) { return Maybe.Nothing; }
+      start = 1;
+    }
+    var dotCount = 0;
+    for (var i = start; i < len; ++i) {
+      if (Char.isDigit(s[i])) { continue; }
+      if (s[i] === '.') {
+        dotCount += 1;
+        if (dotCount <= 1) { continue; }
+      }
+      return Maybe.Nothing;
+    }
+    return Maybe.Just(parseFloat(s));
+  }
+
+  return elm.Native.Prelude = {
+      readInt:readInt,
+      readFloat:readFloat,
+  };
+
+};
+
+Elm.Native.Show = function(elm) {
+    'use strict';
+
+    elm.Native = elm.Native || {};
+    if (elm.Native.Show) return elm.Native.Show;
+
+    var NList = Elm.Native.List(elm);
+    var List = Elm.List(elm);
+    var Maybe = Elm.Maybe(elm);
+    var JS = Elm.JavaScript(elm);
+    var Dict = Elm.Dict(elm);
+    var Json = Elm.Json(elm);
+    var Tuple2 = Elm.Native.Utils(elm).Tuple2;
+
+    var toString = function(v) {
+        if (typeof v === "function") {
+            var name = v.func ? v.func.name : v.name;
+            return '<function' + (name === '' ? '' : ': ') + name + '>';
+        } else if (typeof v === "boolean") {
+            return v ? "True" : "False";
+        } else if (typeof v === "number") {
+            return v+"";
+        } else if (typeof v === "string" && v.length < 2) {
+            return "'" + showChar(v) + "'";
+        } else if (typeof v === "object" && '_' in v) {
+            var output = [];
+            for (var k in v._) {
+                for (var i = v._[k].length; i--; ) {
+                    output.push(k + " = " + toString(v._[k][i]));
+                }
+            }
+            for (var k in v) {
+                if (k === '_') continue;
+                output.push(k + " = " + toString(v[k]));
+            }
+            if (output.length === 0) return "{}";
+            return "{ " + output.join(", ") + " }";
+        } else if (typeof v === "object" && 'ctor' in v) {
+            if (v.ctor.substring(0,6) === "_Tuple") {
+                var output = [];
+                for (var k in v) {
+                    if (k === 'ctor') continue;
+                    output.push(toString(v[k]));
+                }
+                return "(" + output.join(",") + ")";
+            } else if (v.ctor === "::") {
+                var isStr = typeof v._0 === "string",
+                start = isStr ? '"' : "[",
+                end   = isStr ? '"' : "]",
+                sep   = isStr ?  "" : ",",
+                f     = !isStr ? toString : showChar;
+                var output = start + f(v._0);
+                v = v._1;
+                while (v.ctor === "::") {
+                    output += sep + f(v._0);
+                    v = v._1;
+                }
+                return output + end;
+            } else if (v.ctor === "[]") {
+                return "[]";
+            } else if (v.ctor === "RBNode" || v.ctor === "RBEmpty") {
+                var cons = F3(function(k,v,acc){return NList.Cons(Tuple2(k,v),acc)});
+                var list = A3(Dict.foldr, cons, NList.Nil, v);
+                var name = "Dict";
+                if (list.ctor === "::" && list._0._1.ctor === "_Tuple0") {
+                    name = "Set";
+                    list = A2(List.map, function(x){return x._0}, list);
+                }
+                return name + ".fromList " + toString(list);
+            } else {
+                var output = "";
+                for (var i in v) {
+                    if (i === 'ctor') continue;
+                    var str = toString(v[i]);
+                    var parenless = str[0] === '{' || str[0] === '<' || str.indexOf(' ') < 0;
+                    output += ' ' + (parenless ? str : '(' + str + ')');
+                }
+                return v.ctor + output;
+            }
+        }
+        if (typeof v === 'object' && 'recv' in v) return '<signal>';
+        return "<internal structure>";
+    };
+    function show(v) { return NList.fromArray(toString(v)); }
+
+    function showChar (c) {
+        return c === '\n' ? '\\n' :
+               c === '\t' ? '\\t' :
+               c === '\b' ? '\\b' :
+               c === '\r' ? '\\r' :
+               c === '\v' ? '\\v' :
+               c === '\0' ? '\\0' :
+               c === '\'' ? "\\'" :
+               c === '\"' ? '\\"' :
+               c === '\\' ? '\\\\' : c;
+    }
+
+    return elm.Native.Show = { show:show };
+};
+
+Elm.Native.Text = function(elm) {
+  'use strict';
+
+  elm.Native = elm.Native || {};
+  if (elm.Native.Text) return elm.Native.Text;
+
+  var JS = Elm.JavaScript(elm);
+  var htmlHeight = Elm.Native.Utils(elm).htmlHeight;
+  var Color = Elm.Native.Color(elm);
+  var Element = Elm.Graphics.Element(elm);
+  var show = Elm.Native.Show(elm).show;
+
+  function makeSpaces(s) {
+    if (s.length == 0) { return s; }
+    var arr = s.split('');
+    if (arr[0] == ' ') { arr[0] = "&nbsp;" }      
+    for (var i = arr.length; --i; ) {
+      if (arr[i][0] == ' ' && arr[i-1] == ' ') {
+        arr[i-1] = arr[i-1] + arr[i];
+        arr[i] = '';
+      }
+    }
+    for (var i = arr.length; i--; ) {
+      if (arr[i].length > 1 && arr[i][0] == ' ') {
+        var spaces = arr[i].split('');
+        for (var j = spaces.length - 2; j >= 0; j -= 2) {
+          spaces[j] = '&nbsp;';
+        }
+        arr[i] = spaces.join('');
+      }
+    }
+    arr = arr.join('');
+    if (arr[arr.length-1] === " ") {
+	return arr.slice(0,-1) + '&nbsp;';
+    }
+    return arr;
+  }
+
+  function properEscape(str) {
+    if (str.length == 0) return str;
+    str = str //.replace(/&/g,  "&#38;")
+	.replace(/"/g, /*"*/ '&#34;')
+	.replace(/'/g, /*'*/ "&#39;")
+	.replace(/</g,  "&#60;")
+	.replace(/>/g,  "&#62;")
+	.replace(/\n/g, "<br/>");
+    var arr = str.split('<br/>');
+    for (var i = arr.length; i--; ) {
+	arr[i] = makeSpaces(arr[i]);
+    }
+    return arr.join('<br/>');
+  }
+
+  function toText(str) { return properEscape(JS.fromString(str)); }
+
+  function addTag(tag) { return function(text) {
+      return '<' + tag + ' style="padding:0;margin:0">' + text + '</' + tag + '>';
+    }
+  }
+  
+  function addStyle(style, value, text) {
+    return "<span style='" + style + ":" + value + "'>" + text + "</span>";
+  }
+
+  function typeface(name, text) {
+    return addStyle('font-family', JS.fromString(name), text);
+  }
+  function monospace(text) {
+    return addStyle('font-family', 'monospace', text);
+  }
+  function size(px, text) { return addStyle('font-size', px + 'px', text) }
+  var header = addTag('h1');
+  function height(h, text) { return addStyle('font-size', h+'px', text) }
+  function italic(text) { return addStyle('font-style', 'italic', text) }
+  var bold = addTag('b');
+
+  function extract(c) {
+    if (c._3 === 1) { return 'rgb(' + c._0 + ',' + c._1 + ',' + c._2 + ')'; }
+    return 'rgba(' + c._0 + ',' + c._1 + ',' + c._2 + ',' + c._3 + ')';
+  }
+  function color(c, text) {
+    return addStyle('color', extract(c), text);
+  }
+  function underline(text) { return addStyle('text-decoration', 'underline', text) }
+  function overline(text) { return addStyle('text-decoration', 'overline', text) }
+  function strikeThrough(text) {
+      return addStyle('text-decoration', 'line-through', text);
+  }
+  function link(href, text) {
+    return "<a href='" + toText(href) + "'>" + text + "</a>";
+  }
+
+  function position(pos) { return function(text) {
+    var e = {ctor:'RawHtml',
+	     _0: '<div style="padding:0;margin:0;text-align:' +
+                   pos + '">' + text + '</div>'
+            };
+    var p = A2(htmlHeight, 0, text);
+    return A3(Element.newElement, p._0, p._1, e);
+   }
+  }
+
+  function asText(v) {
+      return position('left')(monospace(toText(show(v))));
+  }
+
+  function plainText(v) {
+      return position('left')(toText(v));
+  }
+
+  return elm.Native.Text = {
+      toText: toText,
+
+      header : header,
+      height : F2(height),
+      italic : italic,
+      bold : bold,
+      underline : underline,
+      overline : overline,
+      strikeThrough : strikeThrough,
+      monospace : monospace,
+      typeface : F2(typeface),
+      color : F2(color),
+      link : F2(link),
+
+      justified : position('justify'),
+      centered : position('center'),
+      righted : position('right'),
+      text : position('left'),
+      plainText : plainText,
+
+      asText : asText
+  };
+
+};
+Elm.Native.Utils = function(elm) {
+  'use strict';
+
+  elm.Native = elm.Native || {};
+  if (elm.Native.Utils) return elm.Native.Utils;
+
+  function eq(x,y) {
+    if (x === y) return true;
+    if (typeof x === "object") {
+      var c = 0;
+      for (var i in x) { ++c; if (!eq(x[i],y[i])) return false; }
+      return c === Object.keys(y).length;
+    }
+    if (typeof x === 'function') {
+      throw new Error('Equality error: general function equality is ' +
+      'undecidable, and therefore, unsupported');
+    }
+    return x === y;
+  }
+
+  // code in Generate/JavaScript.hs depends on the particular
+  // integer values assigned to LT, EQ, and GT
+  var LT = -1, EQ = 0, GT = 1, ord = ['LT','EQ','GT'];
+  function compare(x,y) { return { ctor: ord[cmp(x,y)+1] } }
+  function cmp(x,y) {
+    var ord;
+    if (typeof x !== 'object') return x === y ? EQ : x < y ? LT : GT;
+
+    if (x.ctor === "::" || x.ctor === "[]") {
+      while (true) {
+          if (x.ctor === "[]" && y.ctor === "[]") return EQ;
+          if (x.ctor !== y.ctor) return x.ctor === '[]' ? LT : GT;
+          ord = cmp(x._0, y._0);
+          if (ord !== EQ) return ord;
+          x = x._1;
+          y = y._1;
+      }
+    }
+
+    if (x.ctor.slice(0,6) === '_Tuple') {
+      var n = x.ctor.slice(6) - 0;
+      var err = 'cannot compare tuples with more than 6 elements.';
+      if (n === 0) return EQ;
+      if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
+      if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
+      if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
+      if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
+      if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
+      if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
+      if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
+      return EQ;
+    }
+    throw new Error('Comparison error: comparison is only defined on ints, ' +
+        'floats, times, chars, strings, lists of comparable values, ' +
+        'and tuples of comparable values.')
+  }
+
+
+  var Tuple0 = { ctor: "_Tuple0" };
+  function Tuple2(x,y) { return { ctor:"_Tuple2", _0:x, _1:y } }
+
+  var count = 0;
+  function guid(_) { return count++ }
+
+  function copy(r) {
+    var o = {};
+    for (var i in r) { o[i] = r[i]; }
+    return o;
+  }
+
+  function remove(x,r) {
+    var o = copy(r);
+    if (x in o._) {
+      o[x] = o._[x][0];
+      o._[x] = o._[x].slice(1);
+      if (o._[x].length === 0) { delete o._[x]; }
+    } else {
+      delete o[x];
+    }
+    return o;
+  }
+
+  function replace(kvs,r) {
+    var o = copy(r);
+    for (var i = kvs.length; i--; ) {
+      var kvsi = kvs[i];
+      o[kvsi[0]] = kvsi[1];
+    }
+    return o;
+  }
+
+  function insert(x,v,r) {
+    var o = copy(r);
+    if (x in o) o._[x] = [o[x]].concat(x in o._ ? o._[x].slice(0) : []);
+    o[x] = v;
+    return o;
+  }
+
+  function max(a,b) { return a > b ? a : b }
+  function min(a,b) { return a < b ? a : b }
+
+  function mod(a,b) {
+    var r = a % b;
+    var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r+b) : -mod(-a,-b));
+
+    return m === b ? 0 : m;
+  }
+
+  function htmlHeight(width, html) {
+    var t = document.createElement('div');
+    t.innerHTML = html;
+    if (width > 0) { t.style.width = width + "px"; }
+    t.style.visibility = "hidden";
+    t.style.styleFloat = "left";
+    t.style.cssFloat   = "left";
+
+    elm.node.appendChild(t);
+    var style = window.getComputedStyle(t, null);
+    var w = Math.ceil(style.getPropertyValue("width").slice(0,-2) - 0);
+    var h = Math.ceil(style.getPropertyValue("height").slice(0,-2) - 0);
+    elm.node.removeChild(t);
+    return Tuple2(w,h);
+  }
+
+  function adjustOffset() {
+      var node = elm.node;
+      var offsetX = 0, offsetY = 0;
+      if (node.offsetParent) {
+          do {
+              offsetX += node.offsetLeft;
+              offsetY += node.offsetTop;
+          } while (node = node.offsetParent);
+      }
+      elm.node.offsetX = offsetX;
+      elm.node.offsetY = offsetY;
+  }
+
+  if (elm.display === ElmRuntime.Display.COMPONENT) {
+      elm.addListener(elm.inputs, elm.node, 'mouseover', adjustOffset);
+  }
+
+  return elm.Native.Utils = {
+      eq:eq,
+      cmp:cmp,
+      compare:F2(compare),
+      Tuple0:Tuple0,
+      Tuple2:Tuple2,
+      copy: copy,
+      remove: remove,
+      replace: replace,
+      insert: insert,
+      guid: guid,
+      max : F2(max),
+      min : F2(min),
+      mod : F2(mod),
+      htmlHeight: F2(htmlHeight),
+      toFloat: function(x){return x}
+  };
+};
+
+Elm.Native.Graphics.Collage = function(elm) {
+ "use strict";
+
+ elm.Native = elm.Native || {};
+ elm.Native.Graphics = elm.Native.Graphics || {};
+ if (elm.Native.Graphics.Collage) return elm.Native.Graphics.Collage;
+
+ var newElement = Elm.Graphics.Element(elm).newElement;
+ var C = ElmRuntime.use(ElmRuntime.Render.Collage);
+
+ function collage(w,h,forms) {
+     return A3(newElement, w, h, {
+                 ctor: 'Custom',
+		 type: 'Collage',
+		 render: C.render,
+		 update: C.update,
+		 model: {w:w, h:h, forms:forms}
+	 });
+ }
+ return elm.Native.Graphics.Collage = { collage:F3(collage) };
+
+};
+Elm.Native.Graphics.Input = function(elm) {
+ "use strict";
+
+ elm.Native = elm.Native || {};
+ elm.Native.Graphics = elm.Native.Graphics || {};
+ if (elm.Native.Graphics.Input) return elm.Native.Graphics.Input;
+
+ var Render = ElmRuntime.use(ElmRuntime.Render.Element);
+ var newNode = ElmRuntime.use(ElmRuntime.Render.Utils).newElement;
+
+ var Signal = Elm.Signal(elm);
+ var newElement = Elm.Graphics.Element(elm).newElement;
+ var JS = Elm.Native.JavaScript(elm);
+ var Utils = Elm.Native.Utils(elm);
+ var Tuple2 = Utils.Tuple2;
+
+ function dropDown(values) {
+     var entries = JS.fromList(values);
+     var events = Signal.constant(entries[0]._1);
+
+     var drop = newNode('select');
+     drop.style.border = '0 solid';
+     for (var i = 0; i < entries.length; ++i) {
+         var option = newNode('option');
+         var name = JS.fromString(entries[i]._0);
+         option.value = name;
+         option.innerHTML = name;
+         drop.appendChild(option);
+     }
+     drop.addEventListener('change', function() {
+             elm.notify(events.id, entries[drop.selectedIndex]._1);
+         });
+
+     var t = drop.cloneNode(true);
+     t.style.visibility = "hidden";
+
+     elm.node.appendChild(t);
+     var style = window.getComputedStyle(t, null);
+     var w = Math.ceil(style.getPropertyValue("width").slice(0,-2) - 0);
+     var h = Math.ceil(style.getPropertyValue("height").slice(0,-2) - 0);
+     elm.node.removeChild(t);
+     
+     console.log(w,h);
+     var element = A3(newElement, w, h, {
+             ctor: 'Custom',
+             type: 'DropDown',
+             render: function render(model) { return drop; },
+             update: function update(node, oldModel, newModel) {},
+             model: {}
+         });
+
+     return Tuple2(Signal.constant(element), events);
+ }
+
+ function buttons(defaultValue) {
+     var events = Signal.constant(defaultValue);
+
+     function render(model) {
+         var b = newNode('button');
+         b.style.display = 'block';
+         b.elmEvent = model.event;
+         function click() { elm.notify(events.id, b.elmEvent); }
+         b.addEventListener('click', click);
+         b.innerHTML = model.text;
+         return b;
+     }
+
+     function update(node, oldModel, newModel) {
+         node.elmEvent = newModel.event;
+         var txt = newModel.text;
+         if (oldModel.text !== txt) node.innerHTML = txt;
+     }
+
+     function button(evnt, txt) {
+         return A3(newElement, 100, 40, {
+                     ctor: 'Custom',
+                     type: 'Button',
+                     render: render,
+                     update: update,
+                     model: { event:evnt, text:JS.fromString(txt) }
+             });
+     }
+
+     return { _:{}, button:F2(button), events:events };
+ }
+
+ function customButtons(defaultValue) {
+     var events = Signal.constant(defaultValue);
+
+     function render(model) {
+         var btn = newNode('div');
+         btn.elmEvent = model.event;
+
+         btn.elmUp    = Render.render(model.up);
+         btn.elmHover = Render.render(model.hover);
+         btn.elmDown  = Render.render(model.down);
+
+         function replace(node) {
+           if (node !== btn.firstChild) btn.replaceChild(node, btn.firstChild);
+         }
+         var overCount = 0;
+         function over(e) {
+             if (overCount++ > 0) return;
+             replace(btn.elmHover);
+         }
+         function out(e) {
+             if (btn.contains(e.toElement || e.relatedTarget)) return;
+             overCount = 0;
+             replace(btn.elmUp);
+         }
+         function up() {
+             replace(btn.elmHover);
+             elm.notify(events.id, btn.elmEvent);
+         }
+         function down() { replace(btn.elmDown); }
+         btn.addEventListener('mouseover', over);
+         btn.addEventListener('mouseout' , out);
+         btn.addEventListener('mousedown', down);
+         btn.addEventListener('mouseup'  , up);
+
+         btn.appendChild(btn.elmUp);
+
+         var clicker = newNode('div');
+         clicker.style.width = btn.elmUp.style.width;
+         clicker.style.height = btn.elmUp.style.height;
+         clicker.style.position = 'absolute';
+         clicker.style.top = 0;
+         btn.appendChild(clicker);
+
+         return btn;
+     }
+
+     function update(node, oldModel, newModel) {
+         node.elmEvent = newModel.event;
+         Render.update(node.elmUp, oldModel.up, newModel.up)
+         Render.update(node.elmHover, oldModel.hover, newModel.hover)
+         Render.update(node.elmDown, oldModel.down, newModel.down)
+     }
+
+     function button(evnt, up, hover, down) {
+         return A3(newElement,
+                   Math.max(up.props.width, hover.props.width, down.props.width),
+                   Math.max(up.props.height, hover.props.height, down.props.height),
+                   { ctor: 'Custom',
+                     type: 'CustomButton',
+                     render: render,
+                     update: update,
+                     model: { event:evnt, up:up, hover:hover, down:down }
+                   });
+     }
+
+     return { _:{}, customButton:F4(button), events:events };
+ }
+
+
+ function hoverables(defaultValue) {
+     var events = Signal.constant(defaultValue);
+     function hoverable(handler, elem) {
+         function onHover(bool) {
+             elm.notify(events.id, handler(bool));
+         }
+         var props = Utils.replace([['hover',onHover]], elem.props);
+         return { props:props, element:elem.element };
+     }
+     return { _:{}, hoverable:F2(hoverable), events:events };
+ }
+
+
+ function checkboxes(defaultValue) {
+     var events = Signal.constant(defaultValue);
+
+     function render(model) {
+         var b = newNode('input');
+         b.type = 'checkbox';
+         b.checked = model.checked;
+         b.style.display = 'block';
+         b.elmHandler = model.handler;
+         function change() { elm.notify(events.id, b.elmHandler(b.checked)); }
+         b.addEventListener('change', change);
+         return b;
+     }
+
+     function update(node, oldModel, newModel) {
+         node.elmHandler = newModel.handler;
+         node.checked = newModel.checked;
+         return true;
+     }
+
+     function box(handler, checked) {
+         return A3(newElement, 13, 13, {
+                     ctor: 'Custom',
+                     type: 'CheckBox',
+                     render: render,
+                     update: update,
+                     model: { checked:checked, handler:handler  }
+             });
+     }
+
+     return { _:{}, checkbox:F2(box), events:events };
+ }
+
+ function setRange(node, start, end, dir) {
+     if (node.parentNode) {
+         node.setSelectionRange(start, end, dir);
+     } else {
+         setTimeout(function(){node.setSelectionRange(start, end, dir);}, 0);
+     }
+ }
+
+ function mkTextPool(type) { return function fields(defaultValue) {
+     var events = Signal.constant(defaultValue);
+
+     var state = null;
+
+     function render(model) {
+         var field = newNode('input');
+         field.elmHandler = model.handler;
+
+         field.id = 'test';
+         field.type = type;
+         field.placeholder = JS.fromString(model.placeHolder);
+         field.value = JS.fromString(model.state.string);
+         setRange(field, model.state.selectionStart, model.state.selectionEnd, 'forward');
+         field.style.border = 'none';
+         state = model.state;
+
+         function update() {
+             var start = field.selectionStart,
+                 end = field.selectionEnd;
+             if (field.selectionDirection === 'backward') {
+                 start = end;
+                 end = field.selectionStart;
+             }
+             state = { _:{},
+                       string:JS.toString(field.value),
+                       selectionStart:start,
+                       selectionEnd:end };
+             elm.notify(events.id, field.elmHandler(state));
+         }
+         function mousedown() {
+             update();
+             elm.node.addEventListener('mouseup', mouseup);
+         }
+         function mouseup() {
+             update();
+             elm.node.removeEventListener('mouseup', mouseup)
+         }
+         field.addEventListener('keyup', update);
+         field.addEventListener('mousedown', mousedown);
+
+         return field;
+     }
+
+     function update(node, oldModel, newModel) {
+         node.elmHandler = newModel.handler;
+         if (state === newModel.state) return;
+         var newStr = JS.fromString(newModel.state.string);
+         if (node.value !== newStr) node.value = newStr;
+
+         var start = newModel.state.selectionStart;
+         var end = newModel.state.selectionEnd;
+         var direction = 'forward';
+         if (end < start) {
+             start = end;
+             end = newModel.state.selectionStart;
+             direction = 'backward';
+         }
+ 
+         if (node.selectionStart !== start
+             || node.selectionEnd !== end
+             || node.selectionDirection !== direction) {
+             setRange(node, start, end, direction);
+         }
+     }
+
+     function field(handler, placeHolder, state) {
+         return A3(newElement, 200, 30,
+                   { ctor: 'Custom',
+                     type: type + 'Input',
+                     render: render,
+                     update: update,
+                     model: { handler:handler,
+                              placeHolder:placeHolder,
+                              state:state }
+                   });
+     }
+
+     return { _:{}, field:F3(field), events:events };
+   }
+ }
+
+ return elm.Native.Graphics.Input = {
+     buttons:buttons,
+     customButtons:customButtons,
+     hoverables:hoverables,
+     checkboxes:checkboxes,
+     fields:mkTextPool('text'),
+     emails:mkTextPool('email'),
+     passwords:mkTextPool('password'),
+     dropDown:dropDown
+ };
+
+};
+
+Elm.Native.Http = function(elm) {
+  'use strict';
+  elm.Native = elm.Native || {};
+  if (elm.Native.Http) return elm.Native.Http;
+
+
+  var JS = Elm.JavaScript(elm);
+  var List = Elm.List(elm);
+  var Signal = Elm.Signal(elm);
+
+
+  function registerReq(queue,responses) { return function(req) {
+    if (req.url.ctor !== '[]') { sendReq(queue,responses,req); }
+   };
+  }
+
+  function updateQueue(queue,responses) {
+    if (queue.length > 0) {
+      elm.notify(responses.id, queue[0].value);
+      if (queue[0].value.ctor !== 'Waiting') {
+        queue.shift();
+        setTimeout(function() { updateQueue(queue,responses); }, 0);
+      }
+    }
+  }
+
+  function setHeader(pair) {
+    request.setRequestHeader( JS.fromString(pair._0), JS.fromString(pair._1) );
+  }
+
+  function sendReq(queue,responses,req) {
+    var response = { value: { ctor:'Waiting' } };
+    queue.push(response);
+
+    var request = null;
+    if (window.ActiveXObject)  { request = new ActiveXObject("Microsoft.XMLHTTP"); }
+    if (window.XMLHttpRequest) { request = new XMLHttpRequest(); }
+    request.onreadystatechange = function(e) {
+      if (request.readyState === 4) {
+        response.value = (request.status >= 200 && request.status < 300 ?
+        { ctor:'Success', _0:JS.toString(request.responseText) } :
+        { ctor:'Failure', _0:request.status, _1:JS.toString(request.statusText) });
+        setTimeout(function() { updateQueue(queue,responses); }, 0);
+      }
+    };
+    request.open(JS.fromString(req.verb), JS.fromString(req.url), true);
+    List.map(setHeader)(req.headers);
+    request.send(JS.fromString(req.body));
+  }
+
+  function send(requests) {
+    var responses = Signal.constant(elm.Http.Waiting);
+    var sender = A2( Signal.lift, registerReq([],responses), requests );
+    function f(x) { return function(y) { return x; } }
+    return A3( Signal.lift2, f, responses, sender );
+  }
+
+  return elm.Native.Http = {send:send};
+
+};
+
+Elm.Native.Keyboard = function(elm) {
+  'use strict';
+  elm.Native = elm.Native || {};
+  if (elm.Native.Keyboard) return elm.Native.Keyboard;
+
+  var Signal = Elm.Signal(elm);
+  var NList = Elm.Native.List(elm);
+
+  var keysDown = Signal.constant(NList.Nil);
+  var lastKey = Signal.constant('\0');
+
+  elm.addListener([keysDown.id], document, 'keydown', function down(e) {
+          if (NList.member(e.keyCode)(keysDown.value)) return;
+          elm.notify(keysDown.id, NList.Cons(e.keyCode, keysDown.value));
+      });
+  elm.addListener([keysDown.id], document, 'keyup', function up(e) {
+          function notEq(kc) { return kc !== e.keyCode; }
+          elm.notify(keysDown.id, NList.filter(notEq)(keysDown.value));
+      });
+  elm.addListener([keysDown.id], document, 'blur', function blur(e) {
+          elm.notify(keysDown.id, NList.Nil);
+      });
+  elm.addListener([lastKey.id], document, 'keypress', function press(e) {
+          elm.notify(lastKey.id, e.charCode || e.keyCode);
+      });
+
+  function keySignal(f) {
+    var signal = Signal.dropRepeats(A2(Signal.lift, f, keysDown));
+    keysDown.defaultNumberOfKids += 1;
+    signal.defaultNumberOfKids = 0;
+    return signal;
+  }
+
+  function dir(up, down, left, right) {
+    function f(ks) {
+      var x = 0, y = 0;
+      while (ks.ctor === "::") {
+        switch (ks._0) {
+          case left : --x; break;
+          case right: ++x; break;
+          case up   : ++y; break;
+          case down : --y; break;
+        }
+        ks = ks._1;
+      }
+      return { _:{}, x:x, y:y };
+    }
+    return keySignal(f);
+  }
+
+  function is(key) { return keySignal(NList.member(key)); }
+
+  return elm.Native.Keyboard = {
+      isDown:is,
+      directions:F4(dir),
+      keysDown:keysDown,
+      lastPressed:lastKey
+  };
+
+};
+
+Elm.Native.Mouse = function(elm) {
+  'use strict';
+  elm.Native = elm.Native || {};
+  if (elm.Native.Mouse) return elm.Native.Mouse;
+
+  var Signal = Elm.Signal(elm);
+  var Utils = Elm.Native.Utils(elm);
+
+  var position  = Signal.constant(Utils.Tuple2(0,0));
+  position.defaultNumberOfKids = 2;
+
+  // do not move x and y into Elm. By setting their default number
+  // of kids, it is possible to detatch the mouse listeners if
+  // they are not needed.
+  var x = A2( Signal.lift, function(p){return p._0}, position);
+  x.defaultNumberOfKids = 0;
+  var y = A2( Signal.lift, function(p){return p._1}, position);
+  y.defaultNumberOfKids = 0;
+
+  var isDown    = Signal.constant(false);
+  var isClicked = Signal.constant(false);
+  var clicks = Signal.constant(Utils.Tuple0);
+
+  function getXY(e) {
+    var posx = 0;
+    var posy = 0;
+    if (!e) e = window.event;
+    if (e.pageX || e.pageY) {
+	posx = e.pageX;
+	posy = e.pageY;
+    } else if (e.clientX || e.clientY) 	{
+	posx = e.clientX + document.body.scrollLeft +
+	  document.documentElement.scrollLeft;
+	posy = e.clientY + document.body.scrollTop +
+	  document.documentElement.scrollTop;
+    }
+    return Utils.Tuple2(posx-elm.node.offsetX, posy-elm.node.offsetY);
+  }
+
+  var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
+
+  elm.addListener([isClicked.id, clicks.id], node, 'click', function click() {
+          elm.notify(isClicked.id, true);
+          elm.notify(clicks.id, Utils.Tuple0);
+          elm.notify(isClicked.id, false);
+      });
+  elm.addListener([isDown.id], node, 'mousedown', function down() {
+          elm.notify(isDown.id, true);
+      });
+  elm.addListener([isDown.id], node, 'mouseup', function up() {
+          elm.notify(isDown.id, false);
+      });
+  elm.addListener([position.id], node, 'mousemove', function move(e) {
+          elm.notify(position.id, getXY(e));
+      });
+
+  return elm.Native.Mouse = {
+      position: position,
+      x:x,
+      y:y,
+      isClicked: isClicked,
+      isDown: isDown,
+      clicks: clicks
+  };
+};
+Elm.Native.Random = function(elm) {
+  'use strict';
+  elm.Native = elm.Native || {};
+  if (elm.Native.Random) return elm.Native.Random;
+
+  var Signal = Elm.Signal(elm);
+
+  function range(min, max, signal) {
+    function f(x) { return Math.floor(Math.random() * (max-min+1)) + min; }
+    return A2( Signal.lift, f, signal );
+  }
+
+  function flt(signal) {
+    function f(x) { return Math.random(); }
+    return A2( Signal.lift, f, signal );
+  }
+
+  elm.Native.Random = { range: F3(range) };
+  elm.Native.Random['float'] = flt;
+  return elm.Native.Random;
+
+};
+
+Elm.Native.Signal = function(elm) {
+  'use strict';
+
+  elm.Native = elm.Native || {};
+  if (elm.Native.Signal) return elm.Native.Signal;
+
+  var Utils = Elm.Native.Utils(elm);
+  var foldl1 = Elm.List(elm).foldl1;
+
+  function send(node, timestep, changed) {
+    var kids = node.kids;
+    for (var i = kids.length; i--; ) {
+      kids[i].recv(timestep, changed, node.id);
+    }
+  }
+
+  function Input(base) {
+    this.id = Utils.guid();
+    this.value = base;
+    this.kids = [];
+    this.defaultNumberOfKids = 0;
+    this.recv = function(timestep, eid, v) {
+      var changed = eid === this.id;
+      if (changed) { this.value = v; }
+      send(this, timestep, changed);
+      return changed;
+    };
+    elm.inputs.push(this);
+  }
+
+  function LiftN(update, args) {
+    this.id = Utils.guid();
+    this.value = update();
+    this.kids = [];
+
+    var n = args.length;
+    var count = 0;
+    var isChanged = false;
+
+    this.recv = function(timestep, changed, parentID) {
+      ++count;
+      if (changed) { isChanged = true; }
+      if (count == n) {
+        if (isChanged) { this.value = update(); }
+        send(this, timestep, isChanged);
+        isChanged = false;
+        count = 0;
+      }
+    };
+    for (var i = n; i--; ) { args[i].kids.push(this); }
+  }
+
+  function lift(func, a) {
+    function update() { return func(a.value); }
+    return new LiftN(update, [a]);
+  }
+  function lift2(func, a, b) {
+    function update() { return A2( func, a.value, b.value ); }
+    return new LiftN(update, [a,b]);
+  }
+  function lift3(func, a, b, c) {
+    function update() { return A3( func, a.value, b.value, c.value ); }
+    return new LiftN(update, [a,b,c]);
+  }
+  function lift4(func, a, b, c, d) {
+    function update() { return A4( func, a.value, b.value, c.value, d.value ); }
+    return new LiftN(update, [a,b,c,d]);
+  }
+  function lift5(func, a, b, c, d, e) {
+    function update() { return A5( func, a.value, b.value, c.value, d.value, e.value ); }
+    return new LiftN(update, [a,b,c,d,e]);
+  }
+  function lift6(func, a, b, c, d, e, f) {
+    function update() { return A6( func, a.value, b.value, c.value, d.value, e.value, f.value ); }
+    return new LiftN(update, [a,b,c,d,e,f]);
+  }
+  function lift7(func, a, b, c, d, e, f, g) {
+    function update() { return A7( func, a.value, b.value, c.value, d.value, e.value, f.value, g.value ); }
+    return new LiftN(update, [a,b,c,d,e,f,g]);
+  }
+  function lift8(func, a, b, c, d, e, f, g, h) {
+    function update() { return A8( func, a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value ); }
+    return new LiftN(update, [a,b,c,d,e,f,g,h]);
+  }
+
+  function Foldp(step, state, input) {
+    this.id = Utils.guid();
+    this.value = state;
+    this.kids = [];
+
+    this.recv = function(timestep, changed, parentID) {
+      if (changed) {
+          this.value = A2( step, input.value, this.value );
+      }
+      send(this, timestep, changed);
+    };
+    input.kids.push(this);
+  }
+
+  function foldp(step, state, input) {
+      return new Foldp(step, state, input);
+  }
+
+  function DropIf(pred,base,input) {
+    this.id = Utils.guid();
+    this.value = pred(input.value) ? base : input.value;
+    this.kids = [];
+    this.recv = function(timestep, changed, parentID) {
+      var chng = changed && !pred(input.value);
+      if (chng) { this.value = input.value; }
+      send(this, timestep, chng);
+    };
+    input.kids.push(this);
+  }
+
+  function DropRepeats(input) {
+    this.id = Utils.guid();
+    this.value = input.value;
+    this.kids = [];
+    this.recv = function(timestep, changed, parentID) {
+      var chng = changed && !Utils.eq(this.value,input.value);
+      if (chng) { this.value = input.value; }
+      send(this, timestep, chng);
+    };
+    input.kids.push(this);
+  }
+
+  function dropWhen(s1,b,s2) {
+    var pairs = lift2( F2(function(x,y){return {x:x,y:y};}), s1, s2 );
+    var dropped = new DropIf(function(p){return p.x;},{x:true,y:b},pairs);
+    return lift(function(p){return p.y;}, dropped);
+  }
+
+  function timestamp(a) {
+    function update() { return Utils.Tuple2(Date.now(), a.value); }
+    return new LiftN(update, [a]);
+  }
+
+  function SampleOn(s1,s2) {
+    this.id = Utils.guid();
+    this.value = s2.value;
+    this.kids = [];
+
+    var count = 0;
+    var isChanged = false;
+
+    this.recv = function(timestep, changed, parentID) {
+      if (parentID === s1.id) isChanged = changed;
+      ++count;
+      if (count == 2) {
+        if (isChanged) { this.value = s2.value; }
+        send(this, timestep, isChanged);
+        count = 0;
+        isChanged = false;
+      }
+    };
+    s1.kids.push(this);
+    s2.kids.push(this);
+  }
+
+  function sampleOn(s1,s2) { return new SampleOn(s1,s2); }
+
+  function delay(t,s) {
+      var delayed = new Input(s.value);
+      var firstEvent = true;
+      function update(v) {
+        if (firstEvent) { firstEvent = false; return; }
+        setTimeout(function() { elm.notify(delayed.id, v); }, t);
+      }
+      function first(a,b) { return a; }
+      return new SampleOn(delayed, lift2(F2(first), delayed, lift(update,s)));
+  }
+
+  function Merge(s1,s2) {
+      this.id = Utils.guid();
+      this.value = s1.value;
+      this.kids = [];
+
+      var next = null;
+      var count = 0;
+      var isChanged = false;
+
+      this.recv = function(timestep, changed, parentID) {
+        ++count;
+        if (changed) {
+            isChanged = true;
+            if (parentID == s2.id && next === null) { next = s2.value; }
+            if (parentID == s1.id) { next = s1.value; }
+        }
+
+        if (count == 2) {
+            if (isChanged) { this.value = next; next = null; }
+            send(this, timestep, isChanged);
+            isChanged = false;
+            count = 0;
+        }
+      };
+      s1.kids.push(this);
+      s2.kids.push(this);
+  }
+
+  function merge(s1,s2) { return new Merge(s1,s2); }
+  function merges(ss) { return A2(foldl1, F2(merge), ss); }
+
+  return elm.Native.Signal = {
+    constant : function(v) { return new Input(v); },
+    lift  : F2(lift ),
+    lift2 : F3(lift2),
+    lift3 : F4(lift3),
+    lift4 : F5(lift4),
+    lift5 : F6(lift5),
+    lift6 : F7(lift6),
+    lift7 : F8(lift7),
+    lift8 : F9(lift8),
+    foldp : F3(foldp),
+    delay : F2(delay),
+    merge : F2(merge),
+    merges : merges,
+    count : function(s) { return foldp(F2(function(_,c) { return c+1; }), 0, s); },
+    countIf : F2(function(pred,s) {
+      return foldp(F2(function(x,c){
+        return pred(x) ? c+1 : c; }), 0, s)}),
+    keepIf : F3(function(pred,base,sig) {
+      return new DropIf(function(x) {return !pred(x);},base,sig); }),
+    dropIf : F3(function(pred,base,sig) { return new DropIf(pred,base,sig); }),
+    keepWhen : F3(function(s1,b,s2) {
+      return dropWhen(lift(function(b){return !b;},s1), b, s2); }),
+    dropWhen : F3(dropWhen),
+    dropRepeats : function(s) { return new DropRepeats(s);},
+    sampleOn : F2(sampleOn),
+    timestamp : timestamp
+  };
+};
+
+Elm.Native.Time = function(elm) {
+  'use strict';
+
+  var Signal = Elm.Signal(elm);
+  var NS = Elm.Native.Signal(elm);
+  var Maybe = Elm.Maybe(elm);
+  var Utils = Elm.Native.Utils(elm);
+
+  function fpsWhen(desiredFPS, isOn) {
+    var msPerFrame = 1000 / desiredFPS;
+    var prev = Date.now(), curr = prev, diff = 0, wasOn = true;
+    var ticker = Signal.constant(diff);
+    function tick(zero) { return function() {
+        curr = Date.now();
+        diff = zero ? 0 : curr - prev;
+        prev = curr;
+        elm.notify(ticker.id, diff);
+      };
+    }
+    var timeoutID = 0;
+    function f(isOn, t) {
+      if (isOn) {
+        timeoutID = setTimeout(tick(!wasOn && isOn), msPerFrame);
+      } else if (wasOn) {
+        clearTimeout(timeoutID);
+      }
+      wasOn = isOn;
+      return t;
+    }
+    return A3( Signal.lift2, F2(f), isOn, ticker );
+  }
+
+  function everyWhen(t, isOn) {
+    var clock = Signal.constant(Date.now());
+    var id = setInterval(function tellTime() {
+            if (!elm.notify(clock.id, Date.now())) {
+                clearInterval(id);
+            }
+        }, t);
+    return clock;
+  }
+
+  function since(t, s) {
+    function cmp(a,b) { return !Utils.eq(a,b); }
+    var dcount = Signal.count(A2(NS.delay, t, s));
+    return A3( Signal.lift2, F2(cmp), Signal.count(s), dcount );
+  }
+  function read(s) {
+      var t = Date.parse(s);
+      return isNaN(t) ? Maybe.Nothing : Maybe.Just(t);
+  }
+  return elm.Native.Time = {
+      fpsWhen : F2(fpsWhen),
+      fps : function(t) { return fpsWhen(t, Signal.constant(true)); },
+      every : function(t) { return everyWhen(t, Signal.constant(true)) },
+      delay : NS.delay,
+      timestamp : NS.timestamp,
+      since : F2(since),
+      toDate : function(t) { return new window.Date(t); },
+      read   : read
+  };
+
+};
+
+Elm.Native.Touch = function(elm) {
+  'use strict';
+
+  elm.Native = elm.Native || {};
+  if (elm.Native.Touch) return elm.Native.Touch;
+
+  var Signal = Elm.Signal(elm);
+  var JS = Elm.JavaScript(elm);
+  var _ = Elm.Native.Utils(elm);
+
+  function Dict() {
+    this.keys = [];
+    this.values = [];
+
+    this.insert = function(key,value) {
+      this.keys.push(key);
+      this.values.push(value);
+    };
+    this.lookup = function(key) {
+      var i = this.keys.indexOf(key)
+      return i >= 0 ? this.values[i] : {x:0,y:0,t:0};
+    };
+    this.remove = function(key) {
+      var i = this.keys.indexOf(key);
+      if (i < 0) return;
+      var t = this.values[i];
+      this.keys.splice(i,1);
+      this.values.splice(i,1);
+      return t;
+    };
+    this.clear = function() {
+        this.keys = [];
+        this.values = [];
+    };
+  }
+  
+  var root = Signal.constant([]),
+      tapTime = 500,
+      hasTap = false,
+      tap = {_:{},x:0,y:0},
+      dict = new Dict();
+
+  function touch(t) {
+      var r = dict.lookup(t.identifier);
+      return {_ : {},
+	      id: t.identifier,
+	      x : t.pageX - elm.node.offsetX,
+	      y : t.pageY - elm.node.offsetY,
+	      x0: r.x,
+	      y0: r.y,
+	      t0: r.t
+	      };
+  }
+
+  var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
+
+  function start(e) {
+    dict.insert(e.identifier,
+                {x: e.pageX - elm.node.offsetX,
+                 y: e.pageY - elm.node.offsetY,
+                 t: Date.now()});
+  }
+  function end(e) {
+    var t = dict.remove(e.identifier);
+    if (Date.now() - t.t < tapTime) {
+        hasTap = true;
+        tap = {_:{}, x:t.x, y:t.y};
+    }
+  }
+
+  function listen(name, f) {
+    function update(e) {
+      for (var i = e.changedTouches.length; i--; ) { f(e.changedTouches[i]); }
+      var ts = new Array(e.touches.length);
+      for (var i = e.touches.length; i--; ) { ts[i] = touch(e.touches[i]); }
+      elm.notify(root.id, ts);
+      e.preventDefault();
+    }
+    elm.addListener([root.id], node, name, update);
+  }
+
+  listen("touchstart", start);
+  listen("touchmove", function(_){});
+  listen("touchend", end);
+  listen("touchcancel", end);
+  listen("touchleave", end);
+
+  var mouseID = -1;
+  function move(e) {
+      for (var i = root.value.length; i--; ) {
+          if (root.value[i].id === mouseID) {
+              root.value[i].x = e.pageX - elm.node.offsetX;
+              root.value[i].y = e.pageY - elm.node.offsetY;
+              elm.notify(root.id, root.value);
+              break;
+          }
+      }
+  }
+  elm.addListener([root.id], node, "mousedown", function down(e) {
+          node.addEventListener("mousemove", move);
+          e.identifier = mouseID;
+          start(e);
+          root.value.push(touch(e));
+          elm.notify(root.id, root.value);
+      });
+  elm.addListener([root.id], node, "mouseup", function up(e) {
+          node.removeEventListener("mousemove", move);
+          e.identifier = mouseID;
+          end(e);
+          for (var i = root.value.length; i--; ) {
+              if (root.value[i].id === mouseID) {
+                  root.value.splice(i, 1);
+                  --mouseID;
+                  break;
+              }
+          }
+          elm.notify(root.id, root.value);
+      });
+  elm.addListener([root.id], node, "blur", function blur(e) {
+          node.removeEventListener("mousemove", move);
+          if (root.value.length > 0) {
+              elm.notify(root.id, []);
+              --mouseID;
+          }
+          dict.clear();
+      });
+
+  function dependency(f) {
+      var sig = A2( Signal.lift, f, root );
+      root.defaultNumberOfKids += 1;
+      sig.defaultNumberOfKids = 0;
+      return sig;
+  }
+
+  var touches = dependency(JS.toList);
+
+  var taps = function() {
+      var sig = dependency(function(_) { return tap; });
+      sig.defaultNumberOfKids = 1;
+      function pred(_) { var b = hasTap; hasTap = false; return b; }
+      var sig2 = A3( Signal.keepIf, pred, {_:{},x:0,y:0}, sig);
+      sig2.defaultNumberOfKids = 0;
+      return sig2;
+  }();
+
+  return elm.Native.Touch = { touches: touches, taps: taps };
+
+};
+Elm.Native.WebSocket = function(elm) {
+  'use strict';
+
+  elm.Native = elm.Native || {};
+  if (elm.Native.WebSocket) return elm.Native.WebSocket;
+
+  var Signal = Elm.Signal(elm);
+  var JS = Elm.JavaScript(elm);
+  var List = Elm.Native.List(elm);
+
+  function open(url, outgoing) {
+    var incoming = Signal.constant(List.Nil);
+    var ws = new WebSocket(JS.fromString(url));
+
+    var pending = [];
+    var ready = false;
+    
+    ws.onopen = function(e) {
+      var len = pending.length;
+      for (var i = 0; i < len; ++i) { ws.send(pending[i]); }
+      ready = true;
+    };
+    ws.onmessage = function(event) {
+      elm.notify(incoming.id, JS.toString(event.data));
+    };
+    
+    function send(msg) {
+      var s = JS.fromString(msg);
+      ready ? ws.send(s) : pending.push(s);
+    }
+    
+    function take1(x,y) { return x }
+    return A3(Signal.lift2, F2(take1), incoming, A2(Signal.lift, send, outgoing));
+  }
+
+  return elm.Native.WebSocket = { connect: F2(open) };
+};
+
+Elm.Native.Window = function(elm) {
+  'use strict';
+
+  elm.Native = elm.Native || {};
+  if (elm.Native.Window) return elm.Native.Window;
+
+  var Signal = Elm.Signal(elm);
+  var Tuple2 = Elm.Native.Utils(elm).Tuple2;
+
+  function getWidth() { return elm.node.clientWidth; }
+  function getHeight() {
+      if (elm.display === ElmRuntime.Display.FULLSCREEN) {
+          return window.innerHeight;
+      }
+      return elm.node.clientHeight;
+  }
+
+  var dimensions = Signal.constant(Tuple2(getWidth(), getHeight()));
+  dimensions.defaultNumberOfKids = 2;
+
+  // Do not move width and height into Elm. By setting the default number of kids,
+  // the resize listener can be detached.
+  var width  = A2(Signal.lift, function(p){return p._0;}, dimensions);
+  width.defaultNumberOfKids = 0;
+
+  var height = A2(Signal.lift, function(p){return p._1;}, dimensions);
+  height.defaultNumberOfKids = 0;
+
+  function resizeIfNeeded() {
+      var w = getWidth();
+      var h = getHeight();
+      if (dimensions.value._0 === w && dimensions.value._1 === h) return;
+      elm.notify(dimensions.id, Tuple2(w,h));
+  }
+  elm.addListener([dimensions.id], window, 'resize', resizeIfNeeded);
+
+  return elm.Native.Window = {
+      dimensions:dimensions,
+      width:width,
+      height:height,
+      resizeIfNeeded:resizeIfNeeded
+  };
+
+};
+
+Elm.Automaton = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Automaton';
+  var Basics = Elm.Basics(elm);
+  var Signal = Elm.Signal(elm);
+  var List = Elm.List(elm);
+  var Maybe = Elm.Maybe(elm);
+  var _op = {};
+  var enqueue = F2(function(x, arg1){
+    return function(){
+      switch (arg1.ctor) {
+        case '_Tuple2':
+          return {ctor:"_Tuple2", _0:_L.Cons(x,arg1._0), _1:arg1._1};
+      }_E.Case($moduleName,'on line 72, column 22 to 31')}();});
+  var empty = {ctor:"_Tuple2", _0:_J.toList([]), _1:_J.toList([])};
+  var dequeue = function(q){
+    return function(){
+      switch (q.ctor) {
+        case '_Tuple2':
+          switch (q._0.ctor) {
+            case '[]':
+              switch (q._1.ctor) {
+                case '[]':
+                  return Maybe.Nothing;
+              }break;
+          }
+          switch (q._1.ctor) {
+            case '::':
+              return Maybe.Just({ctor:"_Tuple2", _0:q._1._0, _1:{ctor:"_Tuple2", _0:q._0, _1:q._1._1}});
+            case '[]':
+              return dequeue({ctor:"_Tuple2", _0:_J.toList([]), _1:List.reverse(q._0)});
+          }break;
+      }_E.Case($moduleName,'between lines 73 and 76')}();};
+  var Step = function(a){
+    return {ctor:"Step", _0:a};};
+  var hiddenState = F2(function(s, f){
+    return Step(function(x){
+      return function(){
+        var _8 = A2(f, x, s);
+        var out = function(){
+          switch (_8.ctor) {
+            case '_Tuple2':
+              return _8._1;
+          }_E.Case($moduleName,'on line 63, column 46 to 51')}();
+        var s$ = function(){
+          switch (_8.ctor) {
+            case '_Tuple2':
+              return s$;
+          }_E.Case($moduleName,'on line 63, column 46 to 51')}();
+        return {ctor:"_Tuple2", _0:A2(hiddenState, s$, f), _1:out};}();});});
+  var average = function(k){
+    return function(){
+      var stepFull = F2(function(n, arg1){
+        return function(){
+          switch (arg1.ctor) {
+            case '_Tuple3':
+              return function(){
+                var case19 = dequeue(arg1._0);
+                switch (case19.ctor) {
+                  case 'Just':
+                    switch (case19._0.ctor) {
+                      case '_Tuple2':
+                        return function(){
+                          var sum$ = ((arg1._2+n)-case19._0._0);
+                          return {ctor:"_Tuple2", _0:{ctor:"_Tuple3", _0:A2(enqueue, n, case19._0._1), _1:arg1._1, _2:sum$}, _1:(sum$/arg1._1)};}();
+                    }break;
+                  case 'Nothing':
+                    return {ctor:"_Tuple2", _0:{ctor:"_Tuple3", _0:arg1._0, _1:arg1._1, _2:arg1._2}, _1:0};
+                }_E.Case($moduleName,'between lines 85 and 89')}();
+          }_E.Case($moduleName,'between lines 85 and 89')}();});
+      var step = F2(function(n, arg1){
+        return function(){
+          switch (arg1.ctor) {
+            case '_Tuple3':
+              return (_N.eq(arg1._1,k) ? A2(stepFull, n, {ctor:"_Tuple3", _0:arg1._0, _1:arg1._1, _2:arg1._2}) : (Basics.otherwise ? {ctor:"_Tuple2", _0:{ctor:"_Tuple3", _0:A2(enqueue, n, arg1._0), _1:(arg1._1+1), _2:(arg1._2+n)}, _1:((arg1._2+n)/(arg1._1+1))} : _E.If($moduleName,'between lines 82 and 83')));
+          }_E.Case($moduleName,'between lines 82 and 83')}();});
+      return A2(hiddenState, {ctor:"_Tuple3", _0:empty, _1:0, _2:0}, step);}();};
+  var pure = function(f){
+    return Step(function(x){
+      return {ctor:"_Tuple2", _0:pure(f), _1:f(x)};});};
+  var run = F3(function(auto, base, inputs){
+    return function(){
+      var step = F2(function(a, arg1){
+        return function(){
+          switch (arg1.ctor) {
+            case '_Tuple2':
+              switch (arg1._0.ctor) {
+                case 'Step':
+                  return arg1._0._0(a);
+              }break;
+          }_E.Case($moduleName,'on line 18, column 28 to 31')}();});
+      return A2(Signal.lift, function(arg1){
+        return function(){
+          switch (arg1.ctor) {
+            case '_Tuple2':
+              return arg1._1;
+          }_E.Case($moduleName,'on line 19, column 23 to 24')}();}, A3(Signal.foldp, step, {ctor:"_Tuple2", _0:auto, _1:base}, inputs));}();});
+  var state = F2(function(s, f){
+    return Step(function(x){
+      return function(){
+        var s$ = A2(f, x, s);
+        return {ctor:"_Tuple2", _0:A2(state, s$, f), _1:s$};}();});});
+  var count = A2(state, 0, F2(function(arg2, c){
+    return function(){
+      return (c+1);}();}));
+  var step = F2(function(a, arg1){
+    return function(){
+      switch (arg1.ctor) {
+        case 'Step':
+          return arg1._0(a);
+      }_E.Case($moduleName,'on line 23, column 19 to 22')}();});
+  var combine = function(autos){
+    return Step(function(a){
+      return function(){
+        var _37 = List.unzip(A2(List.map, step(a), autos));
+        var autos$ = function(){
+          switch (_37.ctor) {
+            case '_Tuple2':
+              return autos$;
+          }_E.Case($moduleName,'on line 39, column 34 to 59')}();
+        var bs = function(){
+          switch (_37.ctor) {
+            case '_Tuple2':
+              return _37._1;
+          }_E.Case($moduleName,'on line 39, column 34 to 59')}();
+        return {ctor:"_Tuple2", _0:combine(autos$), _1:bs};}();});};
+  _op['>>>'] = F2(function(f, g){
+    return Step(function(a){
+      return function(){
+        var _44 = A2(step, a, f);
+        var b = function(){
+          switch (_44.ctor) {
+            case '_Tuple2':
+              return _44._1;
+          }_E.Case($moduleName,'on line 28, column 29 to 37')}();
+        var f$ = function(){
+          switch (_44.ctor) {
+            case '_Tuple2':
+              return f$;
+          }_E.Case($moduleName,'on line 28, column 29 to 37')}();
+        var _51 = A2(step, b, g);
+        var c = function(){
+          switch (_51.ctor) {
+            case '_Tuple2':
+              return _51._1;
+          }_E.Case($moduleName,'on line 29, column 29 to 37')}();
+        var g$ = function(){
+          switch (_51.ctor) {
+            case '_Tuple2':
+              return g$;
+          }_E.Case($moduleName,'on line 29, column 29 to 37')}();
+        return {ctor:"_Tuple2", _0:A2(_op['>>>'], f$, g$), _1:c};}();});});
+  _op['<<<'] = F2(function(g, f){
+    return A2(_op['>>>'], f, g);});
+  return elm.Automaton = {
+    _op : _op, 
+    run : run, 
+    step : step, 
+    combine : combine, 
+    pure : pure, 
+    state : state, 
+    hiddenState : hiddenState, 
+    count : count, 
+    empty : empty, 
+    enqueue : enqueue, 
+    dequeue : dequeue, 
+    average : average, 
+    Step : Step};};
+Elm.Basics = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Basics';
+  var Native = Native || {};
+  Native.Basics = Elm.Native.Basics(elm);
+  var _op = {};
+  _op['||'] = Native.Basics.or;
+  _op['|>'] = F2(function(x, f){
+    return f(x);});
+  var xor = Native.Basics.xor;
+  var uncurry = Native.Basics.uncurry;
+  var truncate = Native.Basics.truncate;
+  var toFloat = Native.Basics.toFloat;
+  var tan = Native.Basics.tan;
+  var sqrt = Native.Basics.sqrt;
+  var snd = Native.Basics.snd;
+  var sin = Native.Basics.sin;
+  var round = Native.Basics.round;
+  var rem = Native.Basics.rem;
+  var radians = function(t){
+    return t;};
+  var pi = Native.Basics.pi;
+  var otherwise = true;
+  var not = Native.Basics.not;
+  var mod = Native.Basics.mod;
+  var min = Native.Basics.min;
+  var max = Native.Basics.max;
+  var logBase = Native.Basics.logBase;
+  var id = function(x){
+    return x;};
+  var fst = Native.Basics.fst;
+  var floor = Native.Basics.floor;
+  var flip = F3(function(f, b, a){
+    return A2(f, a, b);});
+  var e = Native.Basics.e;
+  var div = Native.Basics.div;
+  var curry = Native.Basics.curry;
+  var cos = Native.Basics.cos;
+  var compare = Native.Basics.compare;
+  var clamp = Native.Basics.clamp;
+  var ceiling = Native.Basics.ceiling;
+  var atan2 = Native.Basics.atan2;
+  var atan = Native.Basics.atan;
+  var asin = Native.Basics.asin;
+  var acos = Native.Basics.acos;
+  var abs = Native.Basics.abs;
+  _op['^'] = Native.Basics.exp;
+  var LT = {ctor:"LT"};
+  var GT = {ctor:"GT"};
+  var EQ = {ctor:"EQ"};
+  _op['>='] = Native.Basics.ge;
+  _op['>'] = Native.Basics.gt;
+  _op['=='] = Native.Basics.eq;
+  _op['<|'] = F2(function(f, x){
+    return f(x);});
+  _op['<='] = Native.Basics.le;
+  _op['<'] = Native.Basics.lt;
+  _op['/='] = Native.Basics.neq;
+  _op['/'] = Native.Basics.floatDiv;
+  _op['.'] = F3(function(f, g, x){
+    return f(g(x));});
+  _op['-'] = Native.Basics.sub;
+  _op['+'] = Native.Basics.add;
+  var toPolar = function(arg1){
+    return function(){
+      switch (arg1.ctor) {
+        case '_Tuple2':
+          return {ctor:"_Tuple2", _0:Native.Basics.sqrt((Math.pow(arg1._0,2)+Math.pow(arg1._1,2))), _1:A2(Native.Basics.atan2, arg1._1, arg1._0)};
+      }_E.Case($moduleName,'on line 29, column 18 to 73')}();};
+  _op['*'] = Native.Basics.mul;
+  var degrees = function(d){
+    return ((d*Native.Basics.pi)/180);};
+  var fromPolar = function(arg1){
+    return function(){
+      switch (arg1.ctor) {
+        case '_Tuple2':
+          return {ctor:"_Tuple2", _0:(arg1._0*Native.Basics.cos(arg1._1)), _1:(arg1._0*Native.Basics.sin(arg1._1))};
+      }_E.Case($moduleName,'on line 24, column 20 to 68')}();};
+  var turns = function(r){
+    return ((2*Native.Basics.pi)*r);};
+  _op['&&'] = Native.Basics.and;
+  return elm.Basics = {
+    _op : _op, 
+    radians : radians, 
+    degrees : degrees, 
+    turns : turns, 
+    fromPolar : fromPolar, 
+    toPolar : toPolar, 
+    div : div, 
+    rem : rem, 
+    mod : mod, 
+    cos : cos, 
+    sin : sin, 
+    tan : tan, 
+    acos : acos, 
+    asin : asin, 
+    atan : atan, 
+    atan2 : atan2, 
+    sqrt : sqrt, 
+    abs : abs, 
+    logBase : logBase, 
+    min : min, 
+    max : max, 
+    clamp : clamp, 
+    pi : pi, 
+    e : e, 
+    compare : compare, 
+    xor : xor, 
+    not : not, 
+    otherwise : otherwise, 
+    round : round, 
+    truncate : truncate, 
+    floor : floor, 
+    ceiling : ceiling, 
+    toFloat : toFloat, 
+    id : id, 
+    fst : fst, 
+    snd : snd, 
+    flip : flip, 
+    curry : curry, 
+    uncurry : uncurry, 
+    LT : LT, 
+    EQ : EQ, 
+    GT : GT};};
+Elm.Char = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Char';
+  var Native = Native || {};
+  Native.Char = Elm.Native.Char(elm);
+  var _op = {};
+  var toUpper = Native.Char.toUpper;
+  var toLower = Native.Char.toLower;
+  var toLocaleUpper = Native.Char.toLocaleUpper;
+  var toLocaleLower = Native.Char.toLocaleLower;
+  var toCode = Native.Char.toCode;
+  var isUpper = Native.Char.isUpper;
+  var isOctDigit = Native.Char.isOctDigit;
+  var isLower = Native.Char.isLower;
+  var isHexDigit = Native.Char.isHexDigit;
+  var isDigit = Native.Char.isDigit;
+  var fromCode = Native.Char.fromCode;
+  return elm.Char = {
+    _op : _op, 
+    isUpper : isUpper, 
+    isLower : isLower, 
+    isDigit : isDigit, 
+    isOctDigit : isOctDigit, 
+    isHexDigit : isHexDigit, 
+    toUpper : toUpper, 
+    toLower : toLower, 
+    toLocaleUpper : toLocaleUpper, 
+    toLocaleLower : toLocaleLower, 
+    toCode : toCode, 
+    fromCode : fromCode};};
+Elm.Color = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Color';
+  var Native = Native || {};
+  Native.Color = Elm.Native.Color(elm);
+  var _op = {};
+  var hsva = Native.Color.hsva;
+  var hsv = Native.Color.hsv;
+  var complement = Native.Color.complement;
+  var Radial = F5(function(a, b, c, d, e){
+    return {ctor:"Radial", _0:a, _1:b, _2:c, _3:d, _4:e};});
+  var radial = Radial;
+  var Linear = F3(function(a, b, c){
+    return {ctor:"Linear", _0:a, _1:b, _2:c};});
+  var linear = Linear;
+  var Color = F4(function(a, b, c, d){
+    return {ctor:"Color", _0:a, _1:b, _2:c, _3:d};});
+  var black = A4(Color, 0, 0, 0, 1);
+  var blue = A4(Color, 0, 0, 255, 1);
+  var cyan = A4(Color, 0, 255, 255, 1);
+  var forestGreen = A4(Color, 34, 139, 34, 1);
+  var gray = A4(Color, 128, 128, 128, 1);
+  var green = A4(Color, 0, 128, 0, 1);
+  var grey = A4(Color, 128, 128, 128, 1);
+  var lime = A4(Color, 0, 255, 0, 1);
+  var magenta = A4(Color, 255, 0, 255, 1);
+  var maroon = A4(Color, 128, 0, 0, 1);
+  var navy = A4(Color, 0, 0, 128, 1);
+  var purple = A4(Color, 128, 0, 128, 1);
+  var red = A4(Color, 255, 0, 0, 1);
+  var rgb = F3(function(r, g, b){
+    return A4(Color, r, g, b, 1);});
+  var rgba = Color;
+  var teal = A4(Color, 0, 128, 128, 1);
+  var violet = A4(Color, 238, 130, 238, 1);
+  var white = A4(Color, 255, 255, 255, 1);
+  var yellow = A4(Color, 255, 255, 0, 1);
+  return elm.Color = {
+    _op : _op, 
+    rgba : rgba, 
+    rgb : rgb, 
+    red : red, 
+    lime : lime, 
+    blue : blue, 
+    yellow : yellow, 
+    cyan : cyan, 
+    magenta : magenta, 
+    black : black, 
+    white : white, 
+    gray : gray, 
+    grey : grey, 
+    maroon : maroon, 
+    navy : navy, 
+    green : green, 
+    teal : teal, 
+    purple : purple, 
+    violet : violet, 
+    forestGreen : forestGreen, 
+    complement : complement, 
+    hsva : hsva, 
+    hsv : hsv, 
+    linear : linear, 
+    radial : radial, 
+    Color : Color, 
+    Linear : Linear, 
+    Radial : Radial};};
+Elm.Date = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Date';
+  var Basics = Elm.Basics(elm);
+  var Native = Native || {};
+  Native.Date = Elm.Native.Date(elm);
+  var Time = Elm.Time(elm);
+  var Maybe = Elm.Maybe(elm);
+  var _op = {};
+  var year = Native.Date.year;
+  var toTime = Native.Date.toTime;
+  var second = Native.Date.second;
+  var read = Native.Date.read;
+  var month = Native.Date.month;
+  var minute = Native.Date.minute;
+  var hour = Native.Date.hour;
+  var dayOfWeek = Native.Date.dayOfWeek;
+  var day = Native.Date.day;
+  var Wed = {ctor:"Wed"};
+  var Tue = {ctor:"Tue"};
+  var Thu = {ctor:"Thu"};
+  var Sun = {ctor:"Sun"};
+  var Sep = {ctor:"Sep"};
+  var Sat = {ctor:"Sat"};
+  var Oct = {ctor:"Oct"};
+  var Nov = {ctor:"Nov"};
+  var Mon = {ctor:"Mon"};
+  var May = {ctor:"May"};
+  var Mar = {ctor:"Mar"};
+  var Jun = {ctor:"Jun"};
+  var Jul = {ctor:"Jul"};
+  var Jan = {ctor:"Jan"};
+  var Fri = {ctor:"Fri"};
+  var Feb = {ctor:"Feb"};
+  var Dec = {ctor:"Dec"};
+  var Date = {ctor:"Date"};
+  var Aug = {ctor:"Aug"};
+  var Apr = {ctor:"Apr"};
+  return elm.Date = {
+    _op : _op, 
+    read : read, 
+    toTime : toTime, 
+    year : year, 
+    month : month, 
+    day : day, 
+    dayOfWeek : dayOfWeek, 
+    hour : hour, 
+    minute : minute, 
+    second : second, 
+    Date : Date, 
+    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};};
+Elm.Dict = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Dict';
+  var Basics = Elm.Basics(elm);
+  var Maybe = Elm.Maybe(elm);
+  var Native = Native || {};
+  Native.Error = Elm.Native.Error(elm);
+  var List = Elm.List(elm);
+  var Native = Native || {};
+  Native.Utils = Elm.Native.Utils(elm);
+  var _op = {};
+  var Red = {ctor:"Red"};
+  var RBNode = F5(function(a, b, c, d, e){
+    return {ctor:"RBNode", _0:a, _1:b, _2:c, _3:d, _4:e};});
+  var isRed = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._0.ctor) {
+            case 'Red':
+              return true;
+          }break;
+      }
+      return false;}();};
+  var isRedLeft = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._3.ctor) {
+            case 'RBNode':
+              switch (t._3._0.ctor) {
+                case 'Red':
+                  return true;
+              }break;
+          }break;
+      }
+      return false;}();};
+  var isRedLeftLeft = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._3.ctor) {
+            case 'RBNode':
+              switch (t._3._3.ctor) {
+                case 'RBNode':
+                  switch (t._3._3._0.ctor) {
+                    case 'Red':
+                      return true;
+                  }break;
+              }break;
+          }break;
+      }
+      return false;}();};
+  var isRedRight = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._4.ctor) {
+            case 'RBNode':
+              switch (t._4._0.ctor) {
+                case 'Red':
+                  return true;
+              }break;
+          }break;
+      }
+      return false;}();};
+  var isRedRightLeft = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._4.ctor) {
+            case 'RBNode':
+              switch (t._4._3.ctor) {
+                case 'RBNode':
+                  switch (t._4._3._0.ctor) {
+                    case 'Red':
+                      return true;
+                  }break;
+              }break;
+          }break;
+      }
+      return false;}();};
+  var rotateLeft = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._4.ctor) {
+            case 'RBNode':
+              return A5(RBNode, t._0, t._4._1, t._4._2, A5(RBNode, Red, t._1, t._2, t._3, t._4._3), t._4._4);
+          }break;
+      }
+      return Native.Error.raise(_str('rotateLeft of a node without enough children'));}();};
+  var rotateLeftIfNeeded = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._4.ctor) {
+            case 'RBNode':
+              switch (t._4._0.ctor) {
+                case 'Red':
+                  return rotateLeft(t);
+              }break;
+          }break;
+      }
+      return t;}();};
+  var rotateRight = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._3.ctor) {
+            case 'RBNode':
+              return A5(RBNode, t._0, t._3._1, t._3._2, t._3._3, A5(RBNode, Red, t._1, t._2, t._3._4, t._4));
+          }break;
+      }
+      return Native.Error.raise(_str('rotateRight of a node without enough children'));}();};
+  var rotateRightIfNeeded = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._3.ctor) {
+            case 'RBNode':
+              switch (t._3._0.ctor) {
+                case 'Red':
+                  switch (t._3._3.ctor) {
+                    case 'RBNode':
+                      switch (t._3._3._0.ctor) {
+                        case 'Red':
+                          return rotateRight(t);
+                      }break;
+                  }break;
+              }break;
+          }break;
+      }
+      return t;}();};
+  var RBEmpty = {ctor:"RBEmpty"};
+  var empty = RBEmpty;
+  var findWithDefault = F3(function(base, k, t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBEmpty':
+          return base;
+        case 'RBNode':
+          return function(){
+            var case115 = A2(Native.Utils.compare, k, t._1);
+            switch (case115.ctor) {
+              case 'EQ':
+                return t._2;
+              case 'GT':
+                return A3(findWithDefault, base, k, t._4);
+              case 'LT':
+                return A3(findWithDefault, base, k, t._3);
+            }_E.Case($moduleName,'between lines 137 and 153')}();
+      }_E.Case($moduleName,'between lines 134 and 153')}();});
+  var foldl = F3(function(f, acc, t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBEmpty':
+          return acc;
+        case 'RBNode':
+          return A3(foldl, f, A3(f, t._1, t._2, A3(foldl, f, acc, t._3)), t._4);
+      }_E.Case($moduleName,'between lines 360 and 362')}();});
+  var foldr = F3(function(f, acc, t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBEmpty':
+          return acc;
+        case 'RBNode':
+          return A3(foldr, f, A3(f, t._1, t._2, A3(foldr, f, acc, t._4)), t._3);
+      }_E.Case($moduleName,'between lines 368 and 370')}();});
+  var keys = function(t){
+    return A3(foldr, F3(function(k, v, acc){
+      return _L.Cons(k,acc);}), _J.toList([]), t);};
+  var toList = function(t){
+    return A3(foldr, F3(function(k, v, acc){
+      return _L.Cons({ctor:"_Tuple2", _0:k, _1:v},acc);}), _J.toList([]), t);};
+  var values = function(t){
+    return A3(foldr, F3(function(k, v, acc){
+      return _L.Cons(v,acc);}), _J.toList([]), t);};
+  var lookup = F2(function(k, t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBEmpty':
+          return Maybe.Nothing;
+        case 'RBNode':
+          return function(){
+            var case134 = A2(Native.Utils.compare, k, t._1);
+            switch (case134.ctor) {
+              case 'EQ':
+                return Maybe.Just(t._2);
+              case 'GT':
+                return A2(lookup, k, t._4);
+              case 'LT':
+                return A2(lookup, k, t._3);
+            }_E.Case($moduleName,'between lines 125 and 128')}();
+      }_E.Case($moduleName,'between lines 122 and 128')}();});
+  var member = F2(function(k, t){
+    return Maybe.isJust(A2(lookup, k, t));});
+  var map = F2(function(f, t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBEmpty':
+          return RBEmpty;
+        case 'RBNode':
+          return A5(RBNode, t._0, t._1, f(t._2), A2(map, f, t._3), A2(map, f, t._4));
+      }_E.Case($moduleName,'between lines 352 and 354')}();});
+  var min = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBEmpty':
+          return Native.Error.raise(_str('(min Empty) is not defined'));
+        case 'RBNode':
+          switch (t._3.ctor) {
+            case 'RBEmpty':
+              return {ctor:"_Tuple2", _0:t._1, _1:t._2};
+          }
+          return min(t._3);
+      }_E.Case($moduleName,'between lines 105 and 117')}();};
+  var Black = {ctor:"Black"};
+  var ensureBlackRoot = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._0.ctor) {
+            case 'Red':
+              return A5(RBNode, Black, t._1, t._2, t._3, t._4);
+          }break;
+      }
+      return t;}();};
+  var otherColor = function(c){
+    return function(){
+      switch (c.ctor) {
+        case 'Black':
+          return Red;
+        case 'Red':
+          return Black;
+      }_E.Case($moduleName,'on line 186, column 16 to 57')}();};
+  var color_flip = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._3.ctor) {
+            case 'RBNode':
+              switch (t._4.ctor) {
+                case 'RBNode':
+                  return A5(RBNode, otherColor(t._0), t._1, t._2, A5(RBNode, otherColor(t._3._0), t._3._1, t._3._2, t._3._3, t._3._4), A5(RBNode, otherColor(t._4._0), t._4._1, t._4._2, t._4._3, t._4._4));
+              }break;
+          }break;
+      }
+      return Native.Error.raise(_str('color_flip called on a Empty or Node with a Empty child'));}();};
+  var color_flipIfNeeded = function(t){
+    return function(){
+      switch (t.ctor) {
+        case 'RBNode':
+          switch (t._3.ctor) {
+            case 'RBNode':
+              switch (t._3._0.ctor) {
+                case 'Red':
+                  switch (t._4.ctor) {
+                    case 'RBNode':
+                      switch (t._4._0.ctor) {
+                        case 'Red':
+                          return color_flip(t);
+                      }break;
+                  }break;
+              }break;
+          }break;
+      }
+      return t;}();};
+  var fixUp = function(t){
+    return color_flipIfNeeded(rotateRightIfNeeded(rotateLeftIfNeeded(t)));};
+  var insert = F3(function(k, v, t){
+    return function(){
+      var ins = function(t){
+        return function(){
+          switch (t.ctor) {
+            case 'RBEmpty':
+              return A5(RBNode, Red, k, v, RBEmpty, RBEmpty);
+            case 'RBNode':
+              return function(){
+                var h = function(){
+                  var case192 = A2(Native.Utils.compare, k, t._1);
+                  switch (case192.ctor) {
+                    case 'EQ':
+                      return A5(RBNode, t._0, t._1, v, t._3, t._4);
+                    case 'GT':
+                      return A5(RBNode, t._0, t._1, t._2, t._3, ins(t._4));
+                    case 'LT':
+                      return A5(RBNode, t._0, t._1, t._2, ins(t._3), t._4);
+                  }_E.Case($moduleName,'between lines 219 and 223')}();
+                return fixUp(h);}();
+          }_E.Case($moduleName,'between lines 216 and 224')}();};
+      return ensureBlackRoot(ins(t));}();});
+  var fromList = function(assocs){
+    return A3(List.foldl, F2(function(arg2, d){
+      return function(){
+        switch (arg2.ctor) {
+          case '_Tuple2':
+            return A3(insert, arg2._0, arg2._1, d);
+        }_E.Case($moduleName,'on line 403, column 43 to 55')}();}), empty, assocs);};
+  var intersect = F2(function(t1, t2){
+    return function(){
+      var combine = F3(function(k, v, t){
+        return (A2(member, k, t2) ? A3(insert, k, v, t) : (Basics.otherwise ? t : _E.If($moduleName,'on line 381, column 22 to 63')));});
+      return A3(foldl, combine, empty, t1);}();});
+  var singleton = F2(function(k, v){
+    return A3(insert, k, v, RBEmpty);});
+  var union = F2(function(t1, t2){
+    return A3(foldl, insert, t2, t1);});
+  var moveRedLeft = function(t){
+    return function(){
+      var t$ = color_flip(t);
+      return function(){
+        switch (t$.ctor) {
+          case 'RBNode':
+            return function(){
+              switch (t$._4.ctor) {
+                case 'RBNode':
+                  switch (t$._4._3.ctor) {
+                    case 'RBNode':
+                      switch (t$._4._3._0.ctor) {
+                        case 'Red':
+                          return color_flip(rotateLeft(A5(RBNode, t$._0, t$._1, t$._2, t$._3, rotateRight(t$._4))));
+                      }break;
+                  }break;
+              }
+              return t$;}();
+        }
+        return t$;}();}();};
+  var moveRedLeftIfNeeded = function(t){
+    return ((isRedLeft(t)||isRedLeftLeft(t)) ? t : (Basics.otherwise ? moveRedLeft(t) : _E.If($moduleName,'on line 286, column 3 to 62')));};
+  var deleteMin = function(t){
+    return function(){
+      var del = function(t){
+        return function(){
+          switch (t.ctor) {
+            case 'RBNode':
+              switch (t._3.ctor) {
+                case 'RBEmpty':
+                  return RBEmpty;
+              }break;
+          }
+          return function(){
+            var case219 = moveRedLeftIfNeeded(t);
+            switch (case219.ctor) {
+              case 'RBEmpty':
+                return RBEmpty;
+              case 'RBNode':
+                return fixUp(A5(RBNode, case219._0, case219._1, case219._2, del(case219._3), case219._4));
+            }_E.Case($moduleName,'between lines 297 and 300')}();}();};
+      return ensureBlackRoot(del(t));}();};
+  var moveRedRight = function(t){
+    return function(){
+      var t$ = color_flip(t);
+      return (isRedLeftLeft(t$) ? color_flip(rotateRight(t$)) : (Basics.otherwise ? t$ : _E.If($moduleName,'on line 282, column 3 to 63')));}();};
+  var moveRedRightIfNeeded = function(t){
+    return ((isRedRight(t)||isRedRightLeft(t)) ? t : (Basics.otherwise ? moveRedRight(t) : _E.If($moduleName,'on line 290, column 3 to 65')));};
+  var remove = F2(function(k, t){
+    return function(){
+      var eq_and_noRightNode = function(t){
+        return function(){
+          switch (t.ctor) {
+            case 'RBNode':
+              switch (t._4.ctor) {
+                case 'RBEmpty':
+                  return _N.eq(k,t._1);
+              }break;
+          }
+          return false;}();};
+      var eq = function(t){
+        return function(){
+          switch (t.ctor) {
+            case 'RBNode':
+              return _N.eq(k,t._1);
+          }
+          return false;}();};
+      var delEQ = function(t){
+        return function(){
+          switch (t.ctor) {
+            case 'RBEmpty':
+              return Native.Error.raise(_str('delEQ called on a Empty'));
+            case 'RBNode':
+              return function(){
+                var _243 = min(t._4);
+                var k$ = function(){
+                  switch (_243.ctor) {
+                    case '_Tuple2':
+                      return k$;
+                  }_E.Case($moduleName,'on line 326, column 53 to 58')}();
+                var v$ = function(){
+                  switch (_243.ctor) {
+                    case '_Tuple2':
+                      return v$;
+                  }_E.Case($moduleName,'on line 326, column 53 to 58')}();
+                return fixUp(A5(RBNode, t._0, k$, v$, t._3, deleteMin(t._4)));}();
+          }_E.Case($moduleName,'between lines 325 and 329')}();};
+      var del = function(t){
+        return function(){
+          switch (t.ctor) {
+            case 'RBEmpty':
+              return RBEmpty;
+            case 'RBNode':
+              return ((_N.cmp(k,t._1)<0) ? delLT(t) : (Basics.otherwise ? function(){
+                var u = (isRedLeft(t) ? rotateRight(t) : (Basics.otherwise ? t : _E.If($moduleName,'on line 336, column 33 to 73')));
+                return (eq_and_noRightNode(u) ? RBEmpty : (Basics.otherwise ? function(){
+                  var t$ = moveRedRightIfNeeded(t);
+                  return (eq(t$) ? delEQ(t$) : (Basics.otherwise ? delGT(t$) : _E.If($moduleName,'on line 339, column 29 to 65')));}() : _E.If($moduleName,'between lines 337 and 339')));}() : _E.If($moduleName,'between lines 335 and 339')));
+          }_E.Case($moduleName,'between lines 332 and 340')}();};
+      var delGT = function(t){
+        return function(){
+          switch (t.ctor) {
+            case 'RBEmpty':
+              return Native.Error.raise(_str('delGT called on a Empty'));
+            case 'RBNode':
+              return fixUp(A5(RBNode, t._0, t._1, t._2, t._3, del(t._4)));
+          }_E.Case($moduleName,'between lines 329 and 332')}();};
+      var delLT = function(t){
+        return function(){
+          var case262 = moveRedLeftIfNeeded(t);
+          switch (case262.ctor) {
+            case 'RBEmpty':
+              return Native.Error.raise(_str('delLT on Empty'));
+            case 'RBNode':
+              return fixUp(A5(RBNode, case262._0, case262._1, case262._2, del(case262._3), case262._4));
+          }_E.Case($moduleName,'between lines 322 and 325')}();};
+      return (A2(member, k, t) ? ensureBlackRoot(del(t)) : (Basics.otherwise ? t : _E.If($moduleName,'on line 340, column 7 to 56')));}();});
+  var diff = F2(function(t1, t2){
+    return A3(foldl, F3(function(k, v, t){
+      return A2(remove, k, t);}), t1, t2);});
+  return elm.Dict = {
+    _op : _op, 
+    empty : empty, 
+    singleton : singleton, 
+    insert : insert, 
+    lookup : lookup, 
+    findWithDefault : findWithDefault, 
+    remove : remove, 
+    member : member, 
+    foldl : foldl, 
+    foldr : foldr, 
+    map : map, 
+    union : union, 
+    intersect : intersect, 
+    diff : diff, 
+    keys : keys, 
+    values : values, 
+    toList : toList, 
+    fromList : fromList};};
+Elm.Either = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Either';
+  var List = Elm.List(elm);
+  var _op = {};
+  var Right = function(a){
+    return {ctor:"Right", _0:a};};
+  var isRight = function(e){
+    return function(){
+      switch (e.ctor) {
+        case 'Right':
+          return true;
+      }
+      return false;}();};
+  var Left = function(a){
+    return {ctor:"Left", _0:a};};
+  var consEither = F2(function(e, arg1){
+    return function(){
+      switch (arg1.ctor) {
+        case '_Tuple2':
+          return function(){
+            switch (e.ctor) {
+              case 'Left':
+                return {ctor:"_Tuple2", _0:_L.Cons(e._0,arg1._0), _1:arg1._1};
+              case 'Right':
+                return {ctor:"_Tuple2", _0:arg1._0, _1:_L.Cons(e._0,arg1._1)};
+            }_E.Case($moduleName,'between lines 50 and 52')}();
+      }_E.Case($moduleName,'between lines 50 and 52')}();});
+  var partition = function(es){
+    return A3(List.foldr, consEither, {ctor:"_Tuple2", _0:_J.toList([]), _1:_J.toList([])}, es);};
+  var consLeft = F2(function(e, vs){
+    return function(){
+      switch (e.ctor) {
+        case 'Left':
+          return _L.Cons(e._0,vs);
+        case 'Right':
+          return vs;
+      }_E.Case($moduleName,'between lines 40 and 42')}();});
+  var lefts = function(es){
+    return A3(List.foldr, consLeft, _J.toList([]), es);};
+  var consRight = F2(function(e, vs){
+    return function(){
+      switch (e.ctor) {
+        case 'Left':
+          return vs;
+        case 'Right':
+          return _L.Cons(e._0,vs);
+      }_E.Case($moduleName,'between lines 45 and 47')}();});
+  var rights = function(es){
+    return A3(List.foldr, consRight, _J.toList([]), es);};
+  var either = F3(function(f, g, e){
+    return function(){
+      switch (e.ctor) {
+        case 'Left':
+          return f(e._0);
+        case 'Right':
+          return g(e._0);
+      }_E.Case($moduleName,'on line 16, column 16 to 60')}();});
+  var isLeft = function(e){
+    return function(){
+      switch (e.ctor) {
+        case 'Left':
+          return true;
+      }
+      return false;}();};
+  return elm.Either = {
+    _op : _op, 
+    either : either, 
+    isLeft : isLeft, 
+    isRight : isRight, 
+    lefts : lefts, 
+    rights : rights, 
+    partition : partition, 
+    consLeft : consLeft, 
+    consRight : consRight, 
+    consEither : consEither, 
+    Left : Left, 
+    Right : Right};};
+Elm.Http = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Http';
+  var Basics = Elm.Basics(elm);
+  var Signal = Elm.Signal(elm);
+  var Native = Native || {};
+  Native.Http = Elm.Native.Http(elm);
+  var _op = {};
+  var send = Native.Http.send;
+  var Waiting = {ctor:"Waiting"};
+  var Success = function(a){
+    return {ctor:"Success", _0:a};};
+  var Request = F4(function(a, b, c, d){
+    return {
+      _:{
+      },
+      body:c,
+      headers:d,
+      url:b,
+      verb:a};});
+  var get = function(url){
+    return A4(Request, _str('GET'), url, _str(''), _J.toList([]));};
+  var sendGet = function(reqs){
+    return send(A2(Signal.lift, get, reqs));};
+  var post = F2(function(url, body){
+    return A4(Request, _str('POST'), url, body, _J.toList([]));});
+  var request = Request;
+  var Failure = F2(function(a, b){
+    return {ctor:"Failure", _0:a, _1:b};});
+  return elm.Http = {
+    _op : _op, 
+    request : request, 
+    get : get, 
+    post : post, 
+    send : send, 
+    sendGet : sendGet, 
+    Success : Success, 
+    Waiting : Waiting, 
+    Failure : Failure};};
+Elm.JavaScript = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'JavaScript';
+  var Native = Native || {};
+  Native.JavaScript = Elm.Native.JavaScript(elm);
+  var Basics = Elm.Basics(elm);
+  var _op = {};
+  var toString = Native.JavaScript.toString;
+  var toList = Native.JavaScript.toList;
+  var toInt = Native.JavaScript.toInt;
+  var toFloat = Native.JavaScript.toFloat;
+  var toBool = Native.JavaScript.toBool;
+  var fromString = Native.JavaScript.fromString;
+  var fromList = Native.JavaScript.fromList;
+  var fromInt = Native.JavaScript.fromInt;
+  var fromFloat = Native.JavaScript.fromFloat;
+  var fromBool = Native.JavaScript.fromBool;
+  var JSString = {ctor:"JSString"};
+  var JSObject = {ctor:"JSObject"};
+  var JSNumber = {ctor:"JSNumber"};
+  var JSDomNode = {ctor:"JSDomNode"};
+  var JSBool = {ctor:"JSBool"};
+  var JSArray = function(a){
+    return {ctor:"JSArray", _0:a};};
+  return elm.JavaScript = {
+    _op : _op, 
+    toList : toList, 
+    toInt : toInt, 
+    toFloat : toFloat, 
+    toBool : toBool, 
+    toString : toString, 
+    fromList : fromList, 
+    fromInt : fromInt, 
+    fromFloat : fromFloat, 
+    fromBool : fromBool, 
+    fromString : fromString, 
+    JSNumber : JSNumber, 
+    JSBool : JSBool, 
+    JSString : JSString, 
+    JSArray : JSArray, 
+    JSDomNode : JSDomNode, 
+    JSObject : JSObject};};
+Elm.Json = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Json';
+  var Basics = Elm.Basics(elm);
+  var Dict = Elm.Dict(elm);
+  var Maybe = Elm.Maybe(elm);
+  var JavaScript = Elm.JavaScript(elm);
+  var Native = Native || {};
+  Native.Json = Elm.Native.Json(elm);
+  var JavaScript = Elm.JavaScript(elm);
+  var _op = {};
+  var toString = F2(function(sep, v){
+    return JavaScript.toString(A2(Native.Json.toJSString, sep, v));});
+  var toJSString = Native.Json.toJSString;
+  var toJSObject = Native.Json.toJSObject;
+  var fromString = function(s){
+    return Native.Json.fromJSString(JavaScript.fromString(s));};
+  var fromJSString = Native.Json.fromJSString;
+  var fromJSObject = Native.Json.fromJSObject;
+  var String = function(a){
+    return {ctor:"String", _0:a};};
+  var Object = function(a){
+    return {ctor:"Object", _0:a};};
+  var Number = function(a){
+    return {ctor:"Number", _0:a};};
+  var Null = {ctor:"Null"};
+  var Boolean = function(a){
+    return {ctor:"Boolean", _0:a};};
+  var Array = function(a){
+    return {ctor:"Array", _0:a};};
+  return elm.Json = {
+    _op : _op, 
+    toString : toString, 
+    toJSString : toJSString, 
+    fromString : fromString, 
+    fromJSString : fromJSString, 
+    fromJSObject : fromJSObject, 
+    toJSObject : toJSObject, 
+    String : String, 
+    Number : Number, 
+    Boolean : Boolean, 
+    Null : Null, 
+    Array : Array, 
+    Object : Object};};
+Elm.Keyboard = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Keyboard';
+  var Signal = Elm.Signal(elm);
+  var Native = Native || {};
+  Native.Keyboard = Elm.Native.Keyboard(elm);
+  var _op = {};
+  var lastPressed = Native.Keyboard.lastPressed;
+  var keysDown = Native.Keyboard.keysDown;
+  var isDown = Native.Keyboard.isDown;
+  var shift = isDown(16);
+  var space = isDown(32);
+  var enter = isDown(13);
+  var directions = Native.Keyboard.directions;
+  var wasd = A4(directions, 87, 83, 65, 68);
+  var ctrl = isDown(17);
+  var arrows = A4(directions, 38, 40, 37, 39);
+  return elm.Keyboard = {
+    _op : _op, 
+    directions : directions, 
+    arrows : arrows, 
+    wasd : wasd, 
+    isDown : isDown, 
+    shift : shift, 
+    ctrl : ctrl, 
+    space : space, 
+    enter : enter, 
+    keysDown : keysDown, 
+    lastPressed : lastPressed};};
+Elm.List = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'List';
+  var Basics = Elm.Basics(elm);
+  var Native = Native || {};
+  Native.List = Elm.Native.List(elm);
+  var _op = {};
+  var zipWith = Native.List.zipWith;
+  var zip = Native.List.zip;
+  var take = Native.List.take;
+  var tail = Native.List.tail;
+  var split = Native.List.split;
+  var scanl1 = Native.List.scanl1;
+  var scanl = Native.List.scanl;
+  var reverse = Native.List.reverse;
+  var map = Native.List.map;
+  var length = Native.List.length;
+  var last = Native.List.last;
+  var join = Native.List.join;
+  var isEmpty = function(xs){
+    return function(){
+      switch (xs.ctor) {
+        case '[]':
+          return true;
+      }
+      return false;}();};
+  var head = Native.List.head;
+  var foldr1 = Native.List.foldr1;
+  var foldr = Native.List.foldr;
+  var foldl1 = Native.List.foldl1;
+  var maximum = foldl1(Basics.max);
+  var minimum = foldl1(Basics.min);
+  var foldl = Native.List.foldl;
+  var or = A2(foldl, F2(function(x, y){
+    return (x||y);}), false);
+  var product = A2(foldl, F2(function(x, y){
+    return (x*y);}), 1);
+  var sum = A2(foldl, F2(function(x, y){
+    return (x+y);}), 0);
+  var filter = Native.List.filter;
+  var drop = Native.List.drop;
+  var concat = Native.List.concat;
+  var concatMap = F2(function(f, list){
+    return concat(A2(map, f, list));});
+  var any = Native.List.any;
+  var and = A2(foldl, F2(function(x, y){
+    return (x&&y);}), true);
+  var all = Native.List.all;
+  _op['::'] = Native.List.cons;
+  var intersperse = F2(function(sep, xs){
+    return function(){
+      switch (xs.ctor) {
+        case '::':
+          switch (xs._1.ctor) {
+            case '::':
+              return _L.Cons(xs._0,_L.Cons(sep,A2(intersperse, sep, _L.Cons(xs._1._0,xs._1._1))));
+            case '[]':
+              return _J.toList([xs._0]);
+          }break;
+        case '[]':
+          return _J.toList([]);
+      }_E.Case($moduleName,'between lines 176 and 179')}();});
+  var partition = F2(function(pred, lst){
+    return function(){
+      switch (lst.ctor) {
+        case '::':
+          return function(){
+            var _9 = A2(partition, pred, lst._1);
+            var bs = function(){
+              switch (_9.ctor) {
+                case '_Tuple2':
+                  return _9._0;
+              }_E.Case($moduleName,'on line 133, column 30 to 47')}();
+            var cs = function(){
+              switch (_9.ctor) {
+                case '_Tuple2':
+                  return _9._1;
+              }_E.Case($moduleName,'on line 133, column 30 to 47')}();
+            return (pred(lst._0) ? {ctor:"_Tuple2", _0:_L.Cons(lst._0,bs), _1:cs} : (Basics.otherwise ? {ctor:"_Tuple2", _0:bs, _1:_L.Cons(lst._0,cs)} : _E.If($moduleName,'on line 134, column 16 to 57')));}();
+        case '[]':
+          return {ctor:"_Tuple2", _0:_J.toList([]), _1:_J.toList([])};
+      }_E.Case($moduleName,'between lines 131 and 134')}();});
+  var unzip = function(pairs){
+    return function(){
+      switch (pairs.ctor) {
+        case '::':
+          switch (pairs._0.ctor) {
+            case '_Tuple2':
+              return function(){
+                var _21 = unzip(pairs._1);
+                var xs = function(){
+                  switch (_21.ctor) {
+                    case '_Tuple2':
+                      return _21._0;
+                  }_E.Case($moduleName,'on line 156, column 33 to 41')}();
+                var ys = function(){
+                  switch (_21.ctor) {
+                    case '_Tuple2':
+                      return _21._1;
+                  }_E.Case($moduleName,'on line 156, column 33 to 41')}();
+                return {ctor:"_Tuple2", _0:_L.Cons(pairs._0._0,xs), _1:_L.Cons(pairs._0._1,ys)};}();
+          }break;
+        case '[]':
+          return {ctor:"_Tuple2", _0:_J.toList([]), _1:_J.toList([])};
+      }_E.Case($moduleName,'between lines 154 and 156')}();};
+  _op['++'] = Native.List.append;
+  return elm.List = {
+    _op : _op, 
+    head : head, 
+    tail : tail, 
+    last : last, 
+    isEmpty : isEmpty, 
+    map : map, 
+    foldl : foldl, 
+    foldr : foldr, 
+    foldl1 : foldl1, 
+    foldr1 : foldr1, 
+    scanl : scanl, 
+    scanl1 : scanl1, 
+    filter : filter, 
+    length : length, 
+    reverse : reverse, 
+    all : all, 
+    any : any, 
+    and : and, 
+    or : or, 
+    concat : concat, 
+    concatMap : concatMap, 
+    sum : sum, 
+    product : product, 
+    maximum : maximum, 
+    minimum : minimum, 
+    partition : partition, 
+    zip : zip, 
+    zipWith : zipWith, 
+    unzip : unzip, 
+    split : split, 
+    join : join, 
+    intersperse : intersperse, 
+    take : take, 
+    drop : drop};};
+Elm.Matrix2D = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Matrix2D';
+  var Native = Native || {};
+  Native.Matrix2D = Elm.Native.Matrix2D(elm);
+  var _op = {};
+  var rotation = Native.Matrix2D.rotation;
+  var multiply = Native.Matrix2D.multiply;
+  var matrix = Native.Matrix2D.matrix;
+  var identity = Native.Matrix2D.identity;
+  var Matrix2D = {ctor:"Matrix2D"};
+  return elm.Matrix2D = {
+    _op : _op, 
+    identity : identity, 
+    matrix : matrix, 
+    rotation : rotation, 
+    multiply : multiply, 
+    Matrix2D : Matrix2D};};
+Elm.Maybe = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Maybe';
+  var Basics = Elm.Basics(elm);
+  var List = Elm.List(elm);
+  var _op = {};
+  var Nothing = {ctor:"Nothing"};
+  var Just = function(a){
+    return {ctor:"Just", _0:a};};
+  var maybe = F3(function(b, f, m){
+    return function(){
+      switch (m.ctor) {
+        case 'Just':
+          return f(m._0);
+        case 'Nothing':
+          return b;
+      }_E.Case($moduleName,'between lines 14 and 16')}();});
+  var cons = F2(function(mx, xs){
+    return A3(maybe, xs, function(x){
+      return _L.Cons(x,xs);}, mx);});
+  var justs = A2(List.foldr, cons, _J.toList([]));
+  var isJust = A2(maybe, false, function(arg1){
+    return function(){
+      return true;}();});
+  var isNothing = function($){
+    return Basics.not(isJust($));};
+  return elm.Maybe = {
+    _op : _op, 
+    maybe : maybe, 
+    isJust : isJust, 
+    isNothing : isNothing, 
+    cons : cons, 
+    justs : justs, 
+    Just : Just, 
+    Nothing : Nothing};};
+Elm.Mouse = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Mouse';
+  var Signal = Elm.Signal(elm);
+  var Native = Native || {};
+  Native.Mouse = Elm.Native.Mouse(elm);
+  var _op = {};
+  var y = Native.Mouse.y;
+  var x = Native.Mouse.x;
+  var position = Native.Mouse.position;
+  var isDown = Native.Mouse.isDown;
+  var isClicked = Native.Mouse.isClicked;
+  var clicks = Native.Mouse.clicks;
+  return elm.Mouse = {
+    _op : _op, 
+    position : position, 
+    x : x, 
+    y : y, 
+    isDown : isDown, 
+    isClicked : isClicked, 
+    clicks : clicks};};
+Elm.Prelude = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Prelude';
+  var Basics = Elm.Basics(elm);
+  var Maybe = Elm.Maybe(elm);
+  var Native = Native || {};
+  Native.Prelude = Elm.Native.Prelude(elm);
+  var Native = Native || {};
+  Native.Show = Elm.Native.Show(elm);
+  var _op = {};
+  var show = Native.Show.show;
+  var readInt = Native.Prelude.readInt;
+  var readFloat = Native.Prelude.readFloat;
+  return elm.Prelude = {
+    _op : _op, 
+    show : show, 
+    readInt : readInt, 
+    readFloat : readFloat};};
+Elm.Random = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Random';
+  var Signal = Elm.Signal(elm);
+  var Native = Native || {};
+  Native.Random = Elm.Native.Random(elm);
+  var _op = {};
+  var range = Native.Random.range;
+  var float = Native.Random.float;
+  return elm.Random = {
+    _op : _op, 
+    range : range, 
+    float : float};};
+Elm.Set = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Set';
+  var Maybe = Elm.Maybe(elm);
+  var Dict = Elm.Dict(elm);
+  var List = Elm.List(elm);
+  var _op = {};
+  var union = Dict.union;
+  var toList = Dict.keys;
+  var singleton = function(k){
+    return A2(Dict.singleton, k, {ctor:"_Tuple0"});};
+  var remove = Dict.remove;
+  var member = Dict.member;
+  var intersect = Dict.intersect;
+  var insert = function(k){
+    return A2(Dict.insert, k, {ctor:"_Tuple0"});};
+  var foldr = F3(function(f, b, s){
+    return A3(Dict.foldr, F3(function(k, arg2, b){
+      return function(){
+        return A2(f, k, b);}();}), b, s);});
+  var foldl = F3(function(f, b, s){
+    return A3(Dict.foldl, F3(function(k, arg2, b){
+      return function(){
+        return A2(f, k, b);}();}), b, s);});
+  var empty = Dict.empty;
+  var fromList = function(xs){
+    return A3(List.foldl, insert, empty, xs);};
+  var map = F2(function(f, s){
+    return fromList(A2(List.map, f, toList(s)));});
+  var diff = Dict.diff;
+  return elm.Set = {
+    _op : _op, 
+    empty : empty, 
+    singleton : singleton, 
+    insert : insert, 
+    remove : remove, 
+    member : member, 
+    foldl : foldl, 
+    foldr : foldr, 
+    map : map, 
+    union : union, 
+    intersect : intersect, 
+    diff : diff, 
+    toList : toList, 
+    fromList : fromList};};
+Elm.Signal = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Signal';
+  var Native = Native || {};
+  Native.Signal = Elm.Native.Signal(elm);
+  var List = Elm.List(elm);
+  var _op = {};
+  _op['~'] = F2(function(sf, s){
+    return A3(Native.Signal.lift2, F2(function(f, x){
+      return f(x);}), sf, s);});
+  var sampleOn = Native.Signal.sampleOn;
+  var merges = Native.Signal.merges;
+  var merge = Native.Signal.merge;
+  var lift8 = Native.Signal.lift8;
+  var lift7 = Native.Signal.lift7;
+  var lift6 = Native.Signal.lift6;
+  var lift5 = Native.Signal.lift5;
+  var lift4 = Native.Signal.lift4;
+  var lift3 = Native.Signal.lift3;
+  var lift2 = Native.Signal.lift2;
+  var lift = Native.Signal.lift;
+  var keepWhen = Native.Signal.keepWhen;
+  var keepIf = Native.Signal.keepIf;
+  var foldp = Native.Signal.foldp;
+  var dropWhen = Native.Signal.dropWhen;
+  var dropRepeats = Native.Signal.dropRepeats;
+  var dropIf = Native.Signal.dropIf;
+  var countIf = Native.Signal.countIf;
+  var count = Native.Signal.count;
+  var constant = Native.Signal.constant;
+  var combine = A2(List.foldr, Native.Signal.lift2(F2(function(x, y){
+    return _L.Cons(x,y);})), Native.Signal.constant(_J.toList([])));
+  var Signal = {ctor:"Signal"};
+  _op['<~'] = F2(function(f, s){
+    return A2(Native.Signal.lift, f, s);});
+  return elm.Signal = {
+    _op : _op, 
+    constant : constant, 
+    lift : lift, 
+    lift2 : lift2, 
+    lift3 : lift3, 
+    lift4 : lift4, 
+    lift5 : lift5, 
+    lift6 : lift6, 
+    lift7 : lift7, 
+    lift8 : lift8, 
+    foldp : foldp, 
+    merge : merge, 
+    merges : merges, 
+    combine : combine, 
+    count : count, 
+    countIf : countIf, 
+    keepIf : keepIf, 
+    dropIf : dropIf, 
+    keepWhen : keepWhen, 
+    dropWhen : dropWhen, 
+    dropRepeats : dropRepeats, 
+    sampleOn : sampleOn, 
+    Signal : Signal};};
+Elm.Text = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Text';
+  var Basics = Elm.Basics(elm);
+  var Color = Elm.Color(elm);
+  var Graphics = Graphics || {};
+  Graphics.Element = Elm.Graphics.Element(elm);
+  var Maybe = Elm.Maybe(elm);
+  var JavaScript = Elm.JavaScript(elm);
+  var Native = Native || {};
+  Native.Text = Elm.Native.Text(elm);
+  var _op = {};
+  var underline = Native.Text.underline;
+  var typeface = Native.Text.typeface;
+  var toText = Native.Text.toText;
+  var text = Native.Text.text;
+  var strikeThrough = Native.Text.strikeThrough;
+  var righted = Native.Text.righted;
+  var plainText = Native.Text.plainText;
+  var overline = Native.Text.overline;
+  var monospace = Native.Text.monospace;
+  var link = Native.Text.link;
+  var justified = Native.Text.justified;
+  var italic = Native.Text.italic;
+  var height = Native.Text.height;
+  var header = Native.Text.header;
+  var color = Native.Text.color;
+  var centered = Native.Text.centered;
+  var bold = Native.Text.bold;
+  var asText = Native.Text.asText;
+  var Text = {ctor:"Text"};
+  return elm.Text = {
+    _op : _op, 
+    toText : toText, 
+    typeface : typeface, 
+    monospace : monospace, 
+    header : header, 
+    link : link, 
+    height : height, 
+    color : color, 
+    bold : bold, 
+    italic : italic, 
+    overline : overline, 
+    underline : underline, 
+    strikeThrough : strikeThrough, 
+    justified : justified, 
+    centered : centered, 
+    righted : righted, 
+    text : text, 
+    plainText : plainText, 
+    asText : asText, 
+    Text : Text};};
+Elm.Time = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Time';
+  var Basics = Elm.Basics(elm);
+  var Native = Native || {};
+  Native.Time = Elm.Native.Time(elm);
+  var Signal = Elm.Signal(elm);
+  var _op = {};
+  var timestamp = Native.Time.timestamp;
+  var since = Native.Time.since;
+  var millisecond = 1;
+  var second = (1000*millisecond);
+  var minute = (60*second);
+  var inSeconds = function(t){
+    return (t/second);};
+  var inMinutes = function(t){
+    return (t/minute);};
+  var inMilliseconds = function(t){
+    return t;};
+  var hour = (60*minute);
+  var inHours = function(t){
+    return (t/hour);};
+  var fpsWhen = Native.Time.fpsWhen;
+  var fps = Native.Time.fps;
+  var every = Native.Time.every;
+  var delay = Native.Time.delay;
+  return elm.Time = {
+    _op : _op, 
+    millisecond : millisecond, 
+    second : second, 
+    minute : minute, 
+    hour : hour, 
+    inMilliseconds : inMilliseconds, 
+    inSeconds : inSeconds, 
+    inMinutes : inMinutes, 
+    inHours : inHours, 
+    fps : fps, 
+    fpsWhen : fpsWhen, 
+    every : every, 
+    since : since, 
+    timestamp : timestamp, 
+    delay : delay};};
+Elm.Touch = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Touch';
+  var Signal = Elm.Signal(elm);
+  var Native = Native || {};
+  Native.Touch = Elm.Native.Touch(elm);
+  var Time = Elm.Time(elm);
+  var _op = {};
+  var touches = Native.Touch.touches;
+  var taps = Native.Touch.taps;
+  var Touch = F6(function(a, b, c, d, e, f){
+    return {
+      _:{
+      },
+      id:c,
+      t0:f,
+      x:a,
+      x0:d,
+      y:b,
+      y0:e};});
+  return elm.Touch = {
+    _op : _op, 
+    touches : touches, 
+    taps : taps};};
+Elm.WebSocket = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'WebSocket';
+  var Signal = Elm.Signal(elm);
+  var Basics = Elm.Basics(elm);
+  var Native = Native || {};
+  Native.WebSocket = Elm.Native.WebSocket(elm);
+  var _op = {};
+  var connect = Native.WebSocket.connect;
+  return elm.WebSocket = {
+    _op : _op, 
+    connect : connect};};
+Elm.Window = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Window';
+  var Signal = Elm.Signal(elm);
+  var Native = Native || {};
+  Native.Window = Elm.Native.Window(elm);
+  var _op = {};
+  var width = Native.Window.width;
+  var height = Native.Window.height;
+  var dimensions = Native.Window.dimensions;
+  return elm.Window = {
+    _op : _op, 
+    dimensions : dimensions, 
+    width : width, 
+    height : height};};
+Elm.Graphics = Elm.Graphics || {};
+Elm.Graphics.Collage = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Graphics.Collage';
+  var Basics = Elm.Basics(elm);
+  var List = Elm.List(elm);
+  var Either = Elm.Either(elm);
+  var Matrix2D = Elm.Matrix2D(elm);
+  var Native = Native || {};
+  Native.Graphics = Native.Graphics || {};
+  Native.Graphics.Collage = Elm.Native.Graphics.Collage(elm);
+  var Graphics = Graphics || {};
+  Graphics.Element = Elm.Graphics.Element(elm);
+  var Color = Elm.Color(elm);
+  var Maybe = Elm.Maybe(elm);
+  var JavaScript = Elm.JavaScript(elm);
+  var _op = {};
+  var segment = F2(function(p1, p2){
+    return _J.toList([p1,p2]);});
+  var scale = F2(function(s, f){
+    return _N.replace([['scale',(f.scale*s)]], f);});
+  var rotate = F2(function(t, f){
+    return _N.replace([['theta',(f.theta+t)]], f);});
+  var rect = F2(function(w, h){
+    return function(){
+      var hw = (w/2);
+      var hh = (h/2);
+      return _J.toList([{ctor:"_Tuple2", _0:(0-hw), _1:(0-hh)},{ctor:"_Tuple2", _0:(0-hw), _1:hh},{ctor:"_Tuple2", _0:hw, _1:hh},{ctor:"_Tuple2", _0:hw, _1:(0-hh)}]);}();});
+  var square = function(n){
+    return A2(rect, n, n);};
+  var polygon = function(points){
+    return points;};
+  var path = function(ps){
+    return ps;};
+  var oval = F2(function(w, h){
+    return function(){
+      var n = 50;
+      var t = ((2*Basics.pi)/n);
+      var hw = (w/2);
+      var hh = (h/2);
+      var f = function(i){
+        return {ctor:"_Tuple2", _0:(hw*Basics.cos((t*i))), _1:(hh*Basics.sin((t*i)))};};
+      return A2(List.map, f, _L.range(0,(n-1)));}();});
+  var ngon = F2(function(n, r){
+    return function(){
+      var m = Basics.toFloat(n);
+      var t = ((2*Basics.pi)/m);
+      var f = function(i){
+        return {ctor:"_Tuple2", _0:(r*Basics.cos((t*i))), _1:(r*Basics.sin((t*i)))};};
+      return A2(List.map, f, _L.range(0,(m-1)));}();});
+  var moveY = F2(function(y, f){
+    return _N.replace([['y',(f.y+y)]], f);});
+  var moveX = F2(function(x, f){
+    return _N.replace([['x',(f.x+x)]], f);});
+  var move = F2(function(arg2, f){
+    return function(){
+      switch (arg2.ctor) {
+        case '_Tuple2':
+          return _N.replace([['x',(f.x+arg2._0)],['y',(f.y+arg2._1)]], f);
+      }_E.Case($moduleName,'on line 142, column 20 to 48')}();});
+  var form = function(f){
+    return {
+      _:{
+      },
+      alpha:1,
+      form:f,
+      scale:1,
+      theta:0,
+      x:0,
+      y:0};};
+  var collage = Native.Graphics.Collage.collage;
+  var circle = function(r){
+    return A2(oval, (2*r), (2*r));};
+  var alpha = F2(function(a, f){
+    return _N.replace([['alpha',a]], f);});
+  var Texture = function(a){
+    return {ctor:"Texture", _0:a};};
+  var Solid = function(a){
+    return {ctor:"Solid", _0:a};};
+  var Smooth = {ctor:"Smooth"};
+  var Sharp = function(a){
+    return {ctor:"Sharp", _0:a};};
+  var Round = {ctor:"Round"};
+  var Padded = {ctor:"Padded"};
+  var LineStyle = F6(function(a, b, c, d, e, f){
+    return {
+      _:{
+      },
+      cap:c,
+      color:a,
+      dashOffset:f,
+      dashing:e,
+      join:d,
+      width:b};});
+  var Grad = function(a){
+    return {ctor:"Grad", _0:a};};
+  var Form = F6(function(a, b, c, d, e, f){
+    return {
+      _:{
+      },
+      alpha:e,
+      form:f,
+      scale:b,
+      theta:a,
+      x:c,
+      y:d};});
+  var Flat = {ctor:"Flat"};
+  var defaultLine = {
+    _:{
+    },
+    cap:Flat,
+    color:Color.black,
+    dashOffset:0,
+    dashing:_J.toList([]),
+    join:Sharp(10),
+    width:1};
+  var dashed = function(clr){
+    return _N.replace([['color',clr],['dashing',_J.toList([8,4])]], defaultLine);};
+  var dotted = function(clr){
+    return _N.replace([['color',clr],['dashing',_J.toList([3,3])]], defaultLine);};
+  var solid = function(clr){
+    return _N.replace([['color',clr]], defaultLine);};
+  var FShape = F2(function(a, b){
+    return {ctor:"FShape", _0:a, _1:b};});
+  var fill = F2(function(style, shape){
+    return form(A2(FShape, Either.Right(style), shape));});
+  var filled = F2(function(color, shape){
+    return A2(fill, Solid(color), shape);});
+  var gradient = F2(function(grad, shape){
+    return A2(fill, Grad(grad), shape);});
+  var textured = F2(function(src, shape){
+    return A2(fill, Texture(src), shape);});
+  var outlined = F2(function(style, shape){
+    return form(A2(FShape, Either.Left(style), shape));});
+  var FPath = F2(function(a, b){
+    return {ctor:"FPath", _0:a, _1:b};});
+  var traced = F2(function(style, path){
+    return form(A2(FPath, style, path));});
+  var FImage = F4(function(a, b, c, d){
+    return {ctor:"FImage", _0:a, _1:b, _2:c, _3:d};});
+  var sprite = F4(function(w, h, pos, src){
+    return form(A4(FImage, w, h, pos, src));});
+  var FGroup = F2(function(a, b){
+    return {ctor:"FGroup", _0:a, _1:b};});
+  var group = function(fs){
+    return form(A2(FGroup, Matrix2D.identity, fs));};
+  var groupTransform = F2(function(matrix, fs){
+    return form(A2(FGroup, matrix, fs));});
+  var FElement = function(a){
+    return {ctor:"FElement", _0:a};};
+  var toForm = function(e){
+    return form(FElement(e));};
+  var Clipped = {ctor:"Clipped"};
+  elm.Graphics = elm.Graphics || {};
+  return elm.Graphics.Collage = {
+    _op : _op, 
+    defaultLine : defaultLine, 
+    solid : solid, 
+    dashed : dashed, 
+    dotted : dotted, 
+    form : form, 
+    fill : fill, 
+    filled : filled, 
+    textured : textured, 
+    gradient : gradient, 
+    outlined : outlined, 
+    traced : traced, 
+    sprite : sprite, 
+    toForm : toForm, 
+    group : group, 
+    groupTransform : groupTransform, 
+    rotate : rotate, 
+    scale : scale, 
+    move : move, 
+    moveX : moveX, 
+    moveY : moveY, 
+    alpha : alpha, 
+    collage : collage, 
+    path : path, 
+    segment : segment, 
+    polygon : polygon, 
+    rect : rect, 
+    square : square, 
+    oval : oval, 
+    circle : circle, 
+    ngon : ngon, 
+    Solid : Solid, 
+    Texture : Texture, 
+    Grad : Grad, 
+    Flat : Flat, 
+    Round : Round, 
+    Padded : Padded, 
+    Smooth : Smooth, 
+    Sharp : Sharp, 
+    Clipped : Clipped, 
+    FPath : FPath, 
+    FShape : FShape, 
+    FImage : FImage, 
+    FElement : FElement, 
+    FGroup : FGroup};};
+Elm.Graphics = Elm.Graphics || {};
+Elm.Graphics.Element = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Graphics.Element';
+  var Basics = Elm.Basics(elm);
+  var Native = Native || {};
+  Native.Utils = Elm.Native.Utils(elm);
+  var JavaScript = Elm.JavaScript(elm);
+  var JavaScript = Elm.JavaScript(elm);
+  var List = Elm.List(elm);
+  var Color = Elm.Color(elm);
+  var Maybe = Elm.Maybe(elm);
+  var _op = {};
+  var widthOf = function(e){
+    return e.props.width;};
+  var tag = F2(function(name, e){
+    return function(){
+      var p = e.props;
+      return {
+        _:{
+        },
+        element:e.element,
+        props:_N.replace([['tag',JavaScript.fromString(name)]], p)};}();});
+  var sizeOf = function(e){
+    return {ctor:"_Tuple2", _0:e.props.width, _1:e.props.height};};
+  var opacity = F2(function(o, e){
+    return function(){
+      var p = e.props;
+      return {
+        _:{
+        },
+        element:e.element,
+        props:_N.replace([['opacity',o]], p)};}();});
+  var markdown = Native.Utils.undefined;
+  var link = F2(function(href, e){
+    return function(){
+      var p = e.props;
+      return {
+        _:{
+        },
+        element:e.element,
+        props:_N.replace([['href',JavaScript.fromString(href)]], p)};}();});
+  var heightOf = function(e){
+    return e.props.height;};
+  var emptyStr = JavaScript.fromString(_str(''));
+  var color = F2(function(c, e){
+    return function(){
+      var p = e.props;
+      return {
+        _:{
+        },
+        element:e.element,
+        props:_N.replace([['color',Maybe.Just(c)]], p)};}();});
+  var Z = {ctor:"Z"};
+  var middleAt = F2(function(x, y){
+    return {
+      _:{
+      },
+      horizontal:Z,
+      vertical:Z,
+      x:x,
+      y:y};});
+  var Tiled = {ctor:"Tiled"};
+  var Spacer = {ctor:"Spacer"};
+  var Relative = function(a){
+    return {ctor:"Relative", _0:a};};
+  var middle = {
+    _:{
+    },
+    horizontal:Z,
+    vertical:Z,
+    x:Relative(0.5),
+    y:Relative(0.5)};
+  var relative = Relative;
+  var RawHtml = function(a){
+    return {ctor:"RawHtml", _0:a};};
+  var Properties = F8(function(a, b, c, d, e, f, g, h){
+    return {
+      _:{
+      },
+      color:e,
+      height:c,
+      hover:h,
+      href:f,
+      id:a,
+      opacity:d,
+      tag:g,
+      width:b};});
+  var newElement = F3(function(w, h, e){
+    return {
+      _:{
+      },
+      element:e,
+      props:A8(Properties, Native.Utils.guid({ctor:"_Tuple0"}), w, h, 1, Maybe.Nothing, emptyStr, emptyStr, {ctor:"_Tuple0"})};});
+  var spacer = F2(function(w, h){
+    return A3(newElement, w, h, Spacer);});
+  var Position = F4(function(a, b, c, d){
+    return {
+      _:{
+      },
+      horizontal:a,
+      vertical:b,
+      x:c,
+      y:d};});
+  var Plain = {ctor:"Plain"};
+  var P = {ctor:"P"};
+  var midRightAt = F2(function(x, y){
+    return {
+      _:{
+      },
+      horizontal:P,
+      vertical:Z,
+      x:x,
+      y:y};});
+  var midTopAt = F2(function(x, y){
+    return {
+      _:{
+      },
+      horizontal:Z,
+      vertical:P,
+      x:x,
+      y:y};});
+  var topRightAt = F2(function(x, y){
+    return {
+      _:{
+      },
+      horizontal:P,
+      vertical:P,
+      x:x,
+      y:y};});
+  var N = {ctor:"N"};
+  var bottomLeftAt = F2(function(x, y){
+    return {
+      _:{
+      },
+      horizontal:N,
+      vertical:N,
+      x:x,
+      y:y};});
+  var bottomRightAt = F2(function(x, y){
+    return {
+      _:{
+      },
+      horizontal:P,
+      vertical:N,
+      x:x,
+      y:y};});
+  var midBottomAt = F2(function(x, y){
+    return {
+      _:{
+      },
+      horizontal:Z,
+      vertical:N,
+      x:x,
+      y:y};});
+  var midLeftAt = F2(function(x, y){
+    return {
+      _:{
+      },
+      horizontal:N,
+      vertical:Z,
+      x:x,
+      y:y};});
+  var topLeftAt = F2(function(x, y){
+    return {
+      _:{
+      },
+      horizontal:N,
+      vertical:P,
+      x:x,
+      y:y};});
+  var Image = F4(function(a, b, c, d){
+    return {ctor:"Image", _0:a, _1:b, _2:c, _3:d};});
+  var height = F2(function(nh, e){
+    return function(){
+      var p = e.props;
+      var props = function(){
+        var case0 = e.element;
+        switch (case0.ctor) {
+          case 'Image':
+            return _N.replace([['width',Basics.round(((Basics.toFloat(case0._1)/Basics.toFloat(case0._2))*Basics.toFloat(nh)))]], p);
+        }
+        return p;}();
+      return {
+        _:{
+        },
+        element:e.element,
+        props:_N.replace([['height',nh]], p)};}();});
+  var image = F3(function(w, h, src){
+    return A3(newElement, w, h, A4(Image, Plain, w, h, JavaScript.fromString(src)));});
+  var tiledImage = F3(function(w, h, src){
+    return A3(newElement, w, h, A4(Image, Tiled, w, h, JavaScript.fromString(src)));});
+  var width = F2(function(nw, e){
+    return function(){
+      var p = e.props;
+      var props = function(){
+        var case5 = e.element;
+        switch (case5.ctor) {
+          case 'Image':
+            return _N.replace([['height',Basics.round(((Basics.toFloat(case5._2)/Basics.toFloat(case5._1))*Basics.toFloat(nw)))]], p);
+          case 'RawHtml':
+            return _N.replace([['height',Basics.snd(A2(Native.Utils.htmlHeight, nw, case5._0))]], p);
+        }
+        return p;}();
+      return {
+        _:{
+        },
+        element:e.element,
+        props:_N.replace([['width',nw]], props)};}();});
+  var size = F3(function(w, h, e){
+    return A2(height, h, A2(width, w, e));});
+  var Flow = F2(function(a, b){
+    return {ctor:"Flow", _0:a, _1:b};});
+  var Fitted = {ctor:"Fitted"};
+  var fittedImage = F3(function(w, h, src){
+    return A3(newElement, w, h, A4(Image, Fitted, w, h, JavaScript.fromString(src)));});
+  var Element = F2(function(a, b){
+    return {
+      _:{
+      },
+      element:b,
+      props:a};});
+  var DUp = {ctor:"DUp"};
+  var up = DUp;
+  var DRight = {ctor:"DRight"};
+  var right = DRight;
+  var beside = F2(function(lft, rht){
+    return A3(newElement, (widthOf(lft)+widthOf(rht)), A2(Basics.max, heightOf(lft), heightOf(rht)), A2(Flow, right, _J.toList([lft,rht])));});
+  var DOut = {ctor:"DOut"};
+  var layers = function(es){
+    return function(){
+      var ws = A2(List.map, widthOf, es);
+      var hs = A2(List.map, heightOf, es);
+      return A3(newElement, List.maximum(ws), List.maximum(hs), A2(Flow, DOut, es));}();};
+  var outward = DOut;
+  var DLeft = {ctor:"DLeft"};
+  var left = DLeft;
+  var DIn = {ctor:"DIn"};
+  var inward = DIn;
+  var DDown = {ctor:"DDown"};
+  var above = F2(function(hi, lo){
+    return A3(newElement, A2(Basics.max, widthOf(hi), widthOf(lo)), (heightOf(hi)+heightOf(lo)), A2(Flow, DDown, _J.toList([hi,lo])));});
+  var below = F2(function(lo, hi){
+    return A3(newElement, A2(Basics.max, widthOf(hi), widthOf(lo)), (heightOf(hi)+heightOf(lo)), A2(Flow, DDown, _J.toList([hi,lo])));});
+  var down = DDown;
+  var flow = F2(function(dir, es){
+    return function(){
+      var ws = A2(List.map, widthOf, es);
+      var newFlow = F2(function(w, h){
+        return A3(newElement, w, h, A2(Flow, dir, es));});
+      var hs = A2(List.map, heightOf, es);
+      return (_N.eq(es,_J.toList([])) ? A2(spacer, 0, 0) : (Basics.otherwise ? function(){
+        switch (dir.ctor) {
+          case 'DDown':
+            return A2(newFlow, List.maximum(ws), List.sum(hs));
+          case 'DIn':
+            return A2(newFlow, List.maximum(ws), List.maximum(hs));
+          case 'DLeft':
+            return A2(newFlow, List.sum(ws), List.maximum(hs));
+          case 'DOut':
+            return A2(newFlow, List.maximum(ws), List.maximum(hs));
+          case 'DRight':
+            return A2(newFlow, List.sum(ws), List.maximum(hs));
+          case 'DUp':
+            return A2(newFlow, List.maximum(ws), List.sum(hs));
+        }_E.Case($moduleName,'between lines 159 and 165')}() : _E.If($moduleName,'between lines 158 and 165')));}();});
+  var Custom = {ctor:"Custom"};
+  var Cropped = function(a){
+    return {ctor:"Cropped", _0:a};};
+  var croppedImage = F4(function(pos, w, h, src){
+    return A3(newElement, w, h, A4(Image, Cropped(pos), w, h, JavaScript.fromString(src)));});
+  var Container = F2(function(a, b){
+    return {ctor:"Container", _0:a, _1:b};});
+  var container = F4(function(w, h, pos, e){
+    return A3(newElement, w, h, A2(Container, pos, e));});
+  var Absolute = function(a){
+    return {ctor:"Absolute", _0:a};};
+  var absolute = Absolute;
+  var midLeft = _N.replace([['horizontal',N],['x',Absolute(0)]], middle);
+  var midRight = _N.replace([['horizontal',P]], midLeft);
+  var midTop = _N.replace([['vertical',P],['y',Absolute(0)]], middle);
+  var midBottom = _N.replace([['vertical',N]], midTop);
+  var topLeft = {
+    _:{
+    },
+    horizontal:N,
+    vertical:P,
+    x:Absolute(0),
+    y:Absolute(0)};
+  var bottomLeft = _N.replace([['vertical',N]], topLeft);
+  var bottomRight = _N.replace([['horizontal',P]], bottomLeft);
+  var topRight = _N.replace([['horizontal',P]], topLeft);
+  elm.Graphics = elm.Graphics || {};
+  return elm.Graphics.Element = {
+    _op : _op, 
+    widthOf : widthOf, 
+    heightOf : heightOf, 
+    sizeOf : sizeOf, 
+    width : width, 
+    height : height, 
+    size : size, 
+    opacity : opacity, 
+    color : color, 
+    tag : tag, 
+    link : link, 
+    emptyStr : emptyStr, 
+    newElement : newElement, 
+    image : image, 
+    fittedImage : fittedImage, 
+    croppedImage : croppedImage, 
+    tiledImage : tiledImage, 
+    markdown : markdown, 
+    container : container, 
+    spacer : spacer, 
+    flow : flow, 
+    above : above, 
+    below : below, 
+    beside : beside, 
+    layers : layers, 
+    absolute : absolute, 
+    relative : relative, 
+    middle : middle, 
+    topLeft : topLeft, 
+    topRight : topRight, 
+    bottomLeft : bottomLeft, 
+    bottomRight : bottomRight, 
+    midLeft : midLeft, 
+    midRight : midRight, 
+    midTop : midTop, 
+    midBottom : midBottom, 
+    middleAt : middleAt, 
+    topLeftAt : topLeftAt, 
+    topRightAt : topRightAt, 
+    bottomLeftAt : bottomLeftAt, 
+    bottomRightAt : bottomRightAt, 
+    midLeftAt : midLeftAt, 
+    midRightAt : midRightAt, 
+    midTopAt : midTopAt, 
+    midBottomAt : midBottomAt, 
+    up : up, 
+    down : down, 
+    left : left, 
+    right : right, 
+    inward : inward, 
+    outward : outward, 
+    Image : Image, 
+    Container : Container, 
+    Flow : Flow, 
+    Spacer : Spacer, 
+    RawHtml : RawHtml, 
+    Custom : Custom, 
+    Plain : Plain, 
+    Fitted : Fitted, 
+    Cropped : Cropped, 
+    Tiled : Tiled, 
+    P : P, 
+    Z : Z, 
+    N : N, 
+    Absolute : Absolute, 
+    Relative : Relative, 
+    DUp : DUp, 
+    DDown : DDown, 
+    DLeft : DLeft, 
+    DRight : DRight, 
+    DIn : DIn, 
+    DOut : DOut};};
+Elm.Graphics = Elm.Graphics || {};
+Elm.Graphics.Input = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'Graphics.Input';
+  var Basics = Elm.Basics(elm);
+  var Signal = Elm.Signal(elm);
+  var Native = Native || {};
+  Native.Graphics = Native.Graphics || {};
+  Native.Graphics.Input = Elm.Native.Graphics.Input(elm);
+  var List = Elm.List(elm);
+  var Graphics = Graphics || {};
+  Graphics.Element = Elm.Graphics.Element(elm);
+  var Color = Elm.Color(elm);
+  var Maybe = Elm.Maybe(elm);
+  var JavaScript = Elm.JavaScript(elm);
+  var _op = {};
+  var id = function(x){
+    return x;};
+  var hoverables = Native.Graphics.Input.hoverables;
+  var hoverable = function(elem){
+    return function(){
+      var pool = hoverables(false);
+      return {ctor:"_Tuple2", _0:A2(pool.hoverable, id, elem), _1:pool.events};}();};
+  var fields = Native.Graphics.Input.fields;
+  var emptyFieldState = {
+    _:{
+    },
+    selectionEnd:0,
+    selectionStart:0,
+    string:_str('')};
+  var field = function(placeHolder){
+    return function(){
+      var tfs = fields(emptyFieldState);
+      var changes = Signal.dropRepeats(tfs.events);
+      return {ctor:"_Tuple2", _0:A2(Signal.lift, A2(tfs.field, id, placeHolder), changes), _1:Signal.dropRepeats(A2(Signal.lift, function(_){
+        return _.string;}, changes))};}();};
+  var password = function(placeHolder){
+    return function(){
+      var tfs = Native.Graphics.Input.passwords(emptyFieldState);
+      var changes = Signal.dropRepeats(tfs.events);
+      return {ctor:"_Tuple2", _0:A2(Signal.lift, A2(tfs.field, id, placeHolder), changes), _1:Signal.dropRepeats(A2(Signal.lift, function(_){
+        return _.string;}, changes))};}();};
+  var email = function(placeHolder){
+    return function(){
+      var tfs = Native.Graphics.Input.emails(emptyFieldState);
+      var changes = Signal.dropRepeats(tfs.events);
+      return {ctor:"_Tuple2", _0:A2(Signal.lift, A2(tfs.field, id, placeHolder), changes), _1:Signal.dropRepeats(A2(Signal.lift, function(_){
+        return _.string;}, changes))};}();};
+  var dropDown = Native.Graphics.Input.dropDown;
+  var stringDropDown = function(strs){
+    return dropDown(A2(List.map, function(s){
+      return {ctor:"_Tuple2", _0:s, _1:s};}, strs));};
+  var customButtons = Native.Graphics.Input.customButtons;
+  var customButton = F3(function(up, hover, down){
+    return function(){
+      var pool = customButtons({ctor:"_Tuple0"});
+      return {ctor:"_Tuple2", _0:A4(pool.customButton, {ctor:"_Tuple0"}, up, hover, down), _1:pool.events};}();});
+  var checkboxes = Native.Graphics.Input.checkboxes;
+  var checkbox = function(b){
+    return function(){
+      var cbs = checkboxes(b);
+      return {ctor:"_Tuple2", _0:A2(Signal.lift, cbs.checkbox(id), cbs.events), _1:cbs.events};}();};
+  var buttons = Native.Graphics.Input.buttons;
+  var button = function(txt){
+    return function(){
+      var pool = buttons({ctor:"_Tuple0"});
+      return {ctor:"_Tuple2", _0:A2(pool.button, {ctor:"_Tuple0"}, txt), _1:pool.events};}();};
+  var FieldState = F3(function(a, b, c){
+    return {
+      _:{
+      },
+      selectionEnd:c,
+      selectionStart:b,
+      string:a};});
+  elm.Graphics = elm.Graphics || {};
+  return elm.Graphics.Input = {
+    _op : _op, 
+    id : id, 
+    buttons : buttons, 
+    button : button, 
+    customButtons : customButtons, 
+    customButton : customButton, 
+    checkboxes : checkboxes, 
+    checkbox : checkbox, 
+    hoverables : hoverables, 
+    hoverable : hoverable, 
+    fields : fields, 
+    emptyFieldState : emptyFieldState, 
+    field : field, 
+    password : password, 
+    email : email, 
+    dropDown : dropDown, 
+    stringDropDown : stringDropDown};};
+Elm.JavaScript = Elm.JavaScript || {};
+Elm.JavaScript.Experimental = function(elm){
+  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _J = N.JavaScript(elm), _str = _J.toString, $moduleName = 'JavaScript.Experimental';
+  var JavaScript = Elm.JavaScript(elm);
+  var Native = Native || {};
+  Native.JavaScript = Elm.Native.JavaScript(elm);
+  var _op = {};
+  var toRecord = Native.JavaScript.toRecord;
+  var fromRecord = Native.JavaScript.fromRecord;
+  elm.JavaScript = elm.JavaScript || {};
+  return elm.JavaScript.Experimental = {
+    _op : _op, 
+    toRecord : toRecord, 
+    fromRecord : fromRecord};};(function() {
+
+// Returns boolean indicating if the swap was successful.
+// Requires that the two signal graphs have exactly the same
+// structure.
+ElmRuntime.swap = function(from, to) {
+    function similar(nodeOld,nodeNew) {
+        idOkay = nodeOld.id === nodeNew.id;
+        lengthOkay = nodeOld.kids.length === nodeNew.kids.length;
+        return idOkay && lengthOkay;
+    }
+    function swap(nodeOld,nodeNew) {
+        nodeNew.value = nodeOld.value;
+        return true;
+    }
+    var canSwap = depthFirstTraversals(similar, from.inputs, to.inputs);
+    if (canSwap) { depthFirstTraversals(swap, from.inputs, to.inputs); }
+    from.node.parentNode.replaceChild(to.node, from.node);
+    return canSwap;
+}
+
+// Returns false if the node operation f ever fails.
+function depthFirstTraversals(f, queueOld, queueNew) {
+    if (queueOld.length !== queueNew.length) return false;
+    queueOld = queueOld.slice(0);
+    queueNew = queueNew.slice(0);
+
+    var seen = [];
+    while (queueOld.length > 0 && queueNew.length > 0) {
+        var nodeOld = queueOld.pop();
+        var nodeNew = queueNew.pop();
+        if (seen.indexOf(nodeOld.id) < 0) {
+            if (!f(nodeOld, nodeNew)) return false;
+            queueOld = queueOld.concat(nodeOld.kids);
+            queueNew = queueNew.concat(nodeNew.kids);
+            seen.push(nodeOld.id);
+        }
+    }
+    return true;
+}
+
+}());
+
+(function() {
+'use strict';
+
+Elm.fullscreen = function(module) {
+    var style = document.createElement('style');
+    style.type = 'text/css';
+    style.innerHTML = "html,head,body { padding:0; margin:0; }" +
+        "body { font-family: calibri, helvetica, arial, sans-serif; }";
+    document.head.appendChild(style);
+    var container = document.createElement('div');
+    document.body.appendChild(container);
+    return init(ElmRuntime.Display.FULLSCREEN, container, module);
+};
+
+Elm.domNode = function(container, module) {
+    var tag = container.tagName;
+    if (tag !== 'DIV') {
+        throw new Error('Elm.node must be given a DIV, not a ' + tag + '.');
+    } else if (container.hasChildNodes()) {
+        throw new Error('Elm.node must be given an empty DIV. No children allowed!');
+    }
+    return init(ElmRuntime.Display.COMPONENT, container, module);
+};
+
+Elm.worker = function(module) {
+    return init(ElmRuntime.Display.NONE, {}, module);
+};
+
+function init(display, container, module, moduleToReplace) {
+  // defining state needed for an instance of the Elm RTS
+  var inputs = [];
+
+  function notify(id, v) {
+      var timestep = Date.now();
+      var changed = false;
+      for (var i = inputs.length; i--; ) {
+          // order is important here to avoid short-circuiting
+          changed = inputs[i].recv(timestep, id, v) || changed;
+      }
+      return changed;
+  }
+
+  container.offsetX = 0;
+  container.offsetY = 0;
+
+  var listeners = [];
+  function addListener(relevantInputs, domNode, eventName, func) {
+      domNode.addEventListener(eventName, func);
+      var listener = {
+          relevantInputs: relevantInputs,
+          domNode: domNode,
+          eventName: eventName,
+          func: func
+      };
+      listeners.push(listener);
+  }
+
+  // create the actual RTS. Any impure modules will attach themselves to this
+  // object. This permits many Elm programs to be embedded per document.
+  var elm = {
+      notify:notify,
+      node:container,
+      display:display,
+      id:ElmRuntime.guid(),
+      addListener:addListener,
+      inputs:inputs
+  };
+
+  // Set up methods to communicate with Elm program from JS.
+  function send(name, value) {
+      if (typeof value === 'undefined') return function(v) { return send(name,v); };
+      var e = document.createEvent('Event');
+      e.initEvent(name + '_' + elm.id, true, true);
+      e.value = value;
+      document.dispatchEvent(e);
+  }
+  function recv(name, handler) {
+      document.addEventListener(name + '_' + elm.id, handler);
+  }
+
+  recv('log', function(e) {console.log(e.value)});
+  recv('title', function(e) {document.title = e.value});
+  recv('redirect', function(e) {
+    if (e.value.length > 0) { window.location = e.value; }
+  });
+
+  function swap(newModule) {
+      removeListeners(listeners);
+      var div = document.createElement('div');
+      var newElm = init(display, div, newModule, elm);
+      inputs = [];
+      // elm.send = newElm.send;
+      // elm.recv = newElm.recv;
+      // elm.swap = newElm.swap;
+      return newElm;
+  }
+
+  var Module = {};
+  var reportAnyErrors = function() {};
+  try {
+      Module = module(elm);
+  } catch(e) {
+      var directions = "<br/>&nbsp; &nbsp; Open the developer console for more details."
+      Module.main = Elm.Text(elm).text('<code>' + e.message + directions + '</code>');
+      reportAnyErrors = function() { throw e; }
+  }
+  inputs = ElmRuntime.filterDeadInputs(inputs);
+  filterListeners(inputs, listeners);
+  if (display !== ElmRuntime.Display.NONE) {
+      var graphicsNode = initGraphics(elm, Module);
+  }
+  if (typeof moduleToReplace !== 'undefined') {
+      ElmRuntime.swap(moduleToReplace, elm);
+
+      // rerender scene if graphics are enabled.
+      if (typeof graphicsNode !== 'undefined') {
+          graphicsNode.recv(0, true, 0);
+      }
+  }
+
+  reportAnyErrors();
+  return { send:send, recv:recv, swap:swap };
+};
+
+function filterListeners(inputs, listeners) {
+    loop:
+    for (var i = listeners.length; i--; ) {
+        var listener = listeners[i];
+        for (var j = inputs.length; j--; ) {
+            if (listener.relevantInputs.indexOf(inputs[j].id) >= 0) {
+                continue loop;
+            }
+        }
+        listener.domNode.removeEventListener(listener.eventName, listener.func);
+    }
+}
+
+function removeListeners(listeners) {
+    for (var i = listeners.length; i--; ) {
+        var listener = listeners[i];
+        listener.domNode.removeEventListener(listener.eventName, listener.func);
+    }
+}
+
+function initGraphics(elm, Module) {
+  if (!('main' in Module))
+      throw new Error("'main' is missing! What do I display?!");
+
+  var signalGraph = Module.main;
+
+  // make sure the signal graph is actually a signal & extract the visual model
+  var Signal = Elm.Signal(elm);
+  if (!('recv' in signalGraph)) {
+      signalGraph = Signal.constant(signalGraph);
+  }
+  var currentScene = signalGraph.value;
+  
+ // Add the currentScene to the DOM
+  var Render = ElmRuntime.use(ElmRuntime.Render.Element);
+  elm.node.appendChild(Render.render(currentScene));
+  
+  // set up updates so that the DOM is adjusted as necessary.
+  function domUpdate(newScene, currentScene) {
+      ElmRuntime.draw(function(_) {
+          Render.update(elm.node.firstChild, currentScene, newScene);
+          if (elm.Native.Window) elm.Native.Window.resizeIfNeeded();
+      });
+      return newScene;
+  }
+  var renderer = A3(Signal.foldp, F2(domUpdate), currentScene, signalGraph);
+
+  // must check for resize after 'renderer' is created so
+  // that changes show up.
+  if (elm.Native.Window) elm.Native.Window.resizeIfNeeded();
+
+  return renderer;
+}
+
+}());
+(function() {
+'use strict';
+
+ElmRuntime.Display = { FULLSCREEN: 0, COMPONENT: 1, NONE: 2 };
+
+ElmRuntime.counter = 0;
+ElmRuntime.guid = function() { return ElmRuntime.counter++; }
+
+ElmRuntime.use = function(M) {
+    if (typeof M === 'function') M = M();
+    return M;
+};
+
+function isAlive(input) {
+    if (!('defaultNumberOfKids' in input)) return true;
+    var len = input.kids.length;
+    if (len === 0) return false;
+    if (len > input.defaultNumberOfKids) return true;
+    var alive = false;
+    for (var i = len; i--; ) {
+        alive = alive || isAlive(input.kids[i]);
+    }
+    return alive;
+}
+
+ElmRuntime.filterDeadInputs = function(inputs) {
+    var temp = [];
+    for (var i = inputs.length; i--; ) {
+        if (isAlive(inputs[i])) temp.push(inputs[i]);
+    }
+    return temp;
+};
+
+// define the draw function
+var vendors = ['ms', 'moz', 'webkit', 'o'];
+for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
+    window.requestAnimationFrame = window[vendors[i]+'RequestAnimationFrame'];
+    window.cancelAnimationFrame  = window[vendors[i]+'CancelAnimationFrame'] ||
+                                   window[vendors[i]+'CancelRequestAnimationFrame'];
+}
+
+if (window.requestAnimationFrame && window.cancelAnimationFrame) {
+    var previous = 0;
+    ElmRuntime.draw = function(callback) {
+        window.cancelAnimationFrame(previous);
+        previous = window.requestAnimationFrame(callback);
+    };
+} else {
+    ElmRuntime.draw = function(callback) { callback(); };
+}
+
+}());
+
+ElmRuntime.Render.Collage = function() {
+'use strict';
+
+var Render = ElmRuntime.use(ElmRuntime.Render.Element);
+var Matrix = Elm.Matrix2D({});
+var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
+var newElement = Utils.newElement,
+    extract = Utils.extract, fromList = Utils.fromList,
+    fromString = Utils.fromString, addTransform = Utils.addTransform;
+
+function trace(ctx, path) {
+    var points = fromList(path);
+    var i = points.length - 1;
+    if (i <= 0) return;
+    ctx.moveTo(points[i]._0, points[i]._1);
+    while (i--) { ctx.lineTo(points[i]._0, points[i]._1); }
+    if (path.closed) {
+        i = points.length - 1;
+        ctx.lineTo(points[i]._0, points[i]._1);
+    }
+}
+
+function line(ctx,style,path) {
+    style.dashing.ctor === 'Nil' ? trace(ctx, path) : customLineHelp(ctx, style, path);
+    ctx.scale(1,-1);
+    ctx.stroke();
+}
+
+function customLineHelp(ctx, style, path) {
+    var points = fromList(path);
+    if (path.closed) points.push(points[0]);
+    var pattern = fromList(style.dashing);
+    var i = points.length - 1;
+    if (i <= 0) return;
+    var x0 = points[i]._0, y0 = points[i]._1;
+    var x1=0, y1=0, dx=0, dy=0, remaining=0, nx=0, ny=0;
+    var pindex = 0, plen = pattern.length;
+    var draw = true, segmentLength = pattern[0];
+    ctx.moveTo(x0,y0);
+    while (i--) {
+        x1 = points[i]._0; y1 = points[i]._1;
+        dx = x1 - x0; dy = y1 - y0;
+        remaining = Math.sqrt(dx * dx + dy * dy);
+        while (segmentLength <= remaining) {
+            x0 += dx * segmentLength / remaining;
+            y0 += dy * segmentLength / remaining;
+            ctx[draw ? 'lineTo' : 'moveTo'](x0, y0);
+            // update starting position
+            dx = x1 - x0; dy = y1 - y0;
+            remaining = Math.sqrt(dx * dx + dy * dy);
+            // update pattern
+            draw = !draw;
+            pindex = (pindex + 1) % plen;
+            segmentLength = pattern[pindex];
+        }
+        if (remaining > 0) {
+            ctx[draw ? 'lineTo' : 'moveTo'](x1, y1);
+            segmentLength -= remaining;
+        }
+        x0 = x1; y0 = y1;
+    }
+}
+
+function drawLine(ctx, style, path) {
+    ctx.lineWidth = style.width;
+    var cap = style.cap.ctor;
+    ctx.lineCap = cap === 'Flat' ? 'butt' :
+                  cap === 'Round' ? 'round' : 'square';
+    var join = style.join.ctor;
+    ctx.lineJoin = join === 'Smooth' ? 'round' :
+                   join === 'Sharp' ? 'miter' : 'bevel';
+    ctx.miterLimit = style.join._0 || 10;
+    ctx.strokeStyle = extract(style.color);
+    return line(ctx, style, path);
+}
+
+function texture(redo, ctx, src) {
+    var img = new Image();
+    img.src = fromString(src);
+    img.onload = redo;
+    return ctx.createPattern(img, 'repeat');
+}
+
+function gradient(ctx, grad) {
+  var g;
+  var stops = [];
+  if (grad.ctor === 'Linear') {
+    var p0 = grad._0, p1 = grad._1;
+    g = ctx.createLinearGradient(p0._0, -p0._1, p1._0, -p1._1);
+    stops = fromList(grad._2);
+  } else {
+    var p0 = grad._0, p2 = grad._2;
+    g = ctx.createRadialGradient(p0._0, -p0._1, grad._1, p2._0, -p2._1, grad._3);
+    stops = fromList(grad._4);
+  }
+  var len = stops.length;
+  for (var i = 0; i < len; ++i) {
+    var stop = stops[i];
+    g.addColorStop(stop._0, extract(stop._1));
+  }
+  return g;
+}
+
+function drawShape(redo, ctx, style, path) {
+    trace(ctx, path);
+    var sty = style.ctor;
+    ctx.fillStyle =
+        sty === 'Solid' ? extract(style._0) :
+        sty === 'Texture' ? texture(redo, ctx, style._0) : gradient(ctx, style._0);
+    ctx.scale(1,-1);
+    ctx.fill();
+}
+
+function drawImage(redo, ctx, form) {
+    var img = new Image();
+    img.onload = redo;
+    img.src = fromString(form._3);
+    var w = form._0,
+        h = form._1,
+        pos = form._2,
+        srcX = pos._0,
+        srcY = pos._1,
+        srcW = w,
+        srcH = h,
+        destX = -w/2,
+        destY = -h/2,
+        destW = w,
+        destH = h;
+
+    ctx.scale(1,-1);
+    ctx.drawImage(img, srcX, srcY, srcW, srcH, destX, destY, destW, destH);
+}
+
+function renderForm(redo, ctx, form) {
+    ctx.save();
+    var x = form.x, y = form.y, theta = form.theta, scale = form.scale;
+    if (x !== 0 || y !== 0) ctx.translate(x, y);
+    if (theta !== 0) ctx.rotate(theta);
+    if (scale !== 1) ctx.scale(scale,scale);
+    if (form.alpha !== 1) ctx.globalAlpha = ctx.globalAlpha * form.alpha;
+    ctx.beginPath();
+    var f = form.form;
+    switch(f.ctor) {
+    case 'FPath' : drawLine(ctx, f._0, f._1); break;
+    case 'FImage': drawImage(redo, ctx, f); break;
+    case 'FShape':
+	if (f._0.ctor === 'Left') {
+	    f._1.closed = true;
+	    drawLine(ctx, f._0._0, f._1);
+	} else {
+            drawShape(redo, ctx, f._0._0, f._1);
+        }
+	break;
+    }
+    ctx.restore();
+}
+
+function formToMatrix(form) {
+   var scale = form.scale;
+   var matrix = A6( Matrix.matrix, scale, 0, 0, scale, form.x, form.y );
+
+   var theta = form.theta
+   if (theta !== 0)
+       matrix = A2( Matrix.multiply, matrix, Matrix.rotation(theta) );
+
+   return matrix;
+}
+
+function makeTransform(w, h, form, matrices) {
+    var props = form.form._0.props;
+    var m = A6( Matrix.matrix, 1, 0, 0, 1,
+                (w - props.width)/2,
+                (h - props.height)/2 );
+    var len = matrices.length;
+    for (var i = 0; i < len; ++i) { m = A2( Matrix.multiply, m, matrices[i] ); }
+    m = A2( Matrix.multiply, m, formToMatrix(form) );
+
+    return 'matrix(' +   m[0]  + ',' +   m[3]  + ',' +
+                       (-m[1]) + ',' + (-m[4]) + ',' +
+                         m[2]  + ',' +   m[5]  + ')';
+}
+
+function stepperHelp(list) {
+    var arr = fromList(list);
+    var i = 0;
+    function peekNext() {
+        return i < arr.length ? arr[i].form.ctor : '';
+    }
+    // assumes that there is a next element
+    function next() {
+        var out = arr[i];
+        ++i;
+        return out;
+    }
+    return { peekNext:peekNext, next:next };
+}
+
+function stepper(forms) {
+    var ps = [stepperHelp(forms)];
+    var matrices = [];
+    var alphas = [];
+    function peekNext() {
+        var len = ps.length;
+        var formType = '';
+        for (var i = 0; i < len; ++i ) {
+            if (formType = ps[i].peekNext()) return formType;
+        }
+        return '';
+    }
+    // assumes that there is a next element
+    function next(ctx) {
+        while (!ps[0].peekNext()) {
+            ps.shift();
+            matrices.pop();
+            alphas.shift();
+            if (ctx) { ctx.restore(); }
+        }
+        var out = ps[0].next();
+        var f = out.form;
+        if (f.ctor === 'FGroup') {
+            ps.unshift(stepperHelp(f._1));
+            var m = A2(Matrix.multiply, f._0, formToMatrix(out));
+            ctx.save();
+            ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
+            matrices.push(m);
+
+            var alpha = (alphas[0] || 1) * out.alpha;
+            alphas.unshift(alpha);
+            ctx.globalAlpha = alpha;
+        }
+        return out;
+    }
+    function transforms() { return matrices; }
+    function alpha() { return alphas[0] || 1; }
+    return { peekNext:peekNext, next:next, transforms:transforms, alpha:alpha };
+}
+
+function makeCanvas(w,h) {
+    var canvas = newElement('canvas');
+    canvas.style.width  = w + 'px';
+    canvas.style.height = h + 'px';
+    canvas.style.display = "block";
+    canvas.style.position = "absolute";
+    canvas.width  = w;
+    canvas.height = h;
+    return canvas;
+}
+
+function render(model) {
+    var div = newElement('div');
+    update(div, model, model);
+    return div;
+}
+
+function updateTracker(w,h,div) {
+    var kids = div.childNodes;
+    var i = 0;
+    function transform(transforms, ctx) {
+        ctx.translate(w/2, h/2);
+        ctx.scale(1,-1);
+        var len = transforms.length;
+        for (var i = 0; i < len; ++i) {
+            var m = transforms[i];
+            ctx.save();
+            ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
+        }
+        return ctx;
+    }
+    function getContext(transforms) {
+        while (i < kids.length) {
+            var node = kids[i];
+            if (node.getContext) {
+                node.width = w;
+                node.height = h;
+                node.style.width = w + 'px';
+                node.style.height = h + 'px';
+                ++i;
+                return transform(transforms, node.getContext('2d'));
+            }
+            div.removeChild(node);
+        }
+        var canvas = makeCanvas(w,h);
+        div.appendChild(canvas);
+        // we have added a new node, so we must step our position
+        ++i;
+        return transform(transforms, canvas.getContext('2d'));
+    }
+    function element(matrices, alpha, form) {
+        var container = kids[i];
+        if (!container || container.getContext) {
+            container = newElement('div');
+            container.style.overflow = 'hidden';
+            container.style.position = 'absolute';
+            addTransform(container.style, 'scaleY(-1)');
+            
+            var kid = kids[i];
+            kid ? div.insertBefore(container, kid)
+                : div.appendChild(container);
+        }
+        // we have added a new node, so we must step our position
+        ++i;
+
+        container.style.width = w + 'px';
+        container.style.height = h + 'px';
+        container.style.opacity = alpha * form.alpha;
+
+        var elem = form.form._0;
+        var node = container.firstChild;
+        if (node) {
+            Render.update(node, node.oldElement, elem);
+            node = container.firstChild;
+        } else {
+            node = Render.render(elem);
+            container.appendChild(node);
+        }
+        node.oldElement = elem;
+        addTransform(node.style, makeTransform(w, h, form, matrices));
+    }
+    function clearRest() {
+        while (i < kids.length) {
+            div.removeChild(kids[i]);
+        }
+    }
+    return { getContext:getContext, element:element, clearRest:clearRest };
+}
+
+
+function update(div, _, model) {
+    var w = model.w;
+    var h = model.h;
+    div.style.width = w + 'px';
+    div.style.height = h + 'px';
+    if (model.forms.ctor === 'Nil') {
+        while (div.hasChildNodes()) {
+            div.removeChild(div.lastChild);
+        }
+    }
+    var stpr = stepper(model.forms);
+    var tracker = updateTracker(w,h,div);
+    var ctx = null;
+    var formType = '';
+
+    while (formType = stpr.peekNext()) {
+        if (ctx === null && formType !== 'FElement') {
+            ctx = tracker.getContext(stpr.transforms());
+            ctx.globalAlpha = stpr.alpha();
+        }
+        var form = stpr.next(ctx);
+        if (formType === 'FElement') {
+            tracker.element(stpr.transforms(), stpr.alpha(), form);
+            ctx = null;
+        } else if (formType !== 'FGroup') {
+            renderForm(function() { update(div, model, model); }, ctx, form);
+        }
+    }
+    tracker.clearRest();
+    return false;
+}
+
+return { render:render, update:update };
+
+};
+
+ElmRuntime.Render.Element = function() {
+'use strict';
+
+var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
+var newElement = Utils.newElement, extract = Utils.extract,
+    addTransform = Utils.addTransform, removeTransform = Utils.removeTransform,
+    fromList = Utils.fromList, eq = Utils.eq;
+
+function setProps(props, e) {
+    e.style.width  = (props.width |0) + 'px';
+    e.style.height = (props.height|0) + 'px';
+    if (props.opacity !== 1) { e.style.opacity = props.opacity; }
+    if (props.color.ctor === 'Just') {
+        e.style.backgroundColor = extract(props.color._0);
+    }
+    if (props.tag !== '') { e.id = props.tag; }
+    if (props.href !== '') {
+        var a = newElement('a');
+        a.href = props.href;
+        a.style.width = '100%';
+        a.style.height = '100%';
+        a.style.top = 0;
+        a.style.left = 0;
+        a.style.display = 'block';
+        a.style.position = 'absolute';
+        e.style.position = 'relative';
+        e.appendChild(a);
+    }
+    if (props.hover.ctor !== '_Tuple0') {
+        var overCount = 0;
+        e.addEventListener('mouseover', function() {
+            if (overCount++ > 0) return;
+            props.hover(true);
+        });
+        e.addEventListener('mouseout', function(evt) {
+            if (e.contains(evt.toElement || evt.relatedTarget)) return;
+            overCount = 0;
+            props.hover(false);
+        });
+    }
+    return e;
+}
+
+function image(props, img) {
+    switch (img._0.ctor) {
+    case 'Plain':   return plainImage(img._3);
+    case 'Fitted':  return fittedImage(props.width, props.height, img._3);
+    case 'Cropped': return croppedImage(img,props.width,props.height,img._3);
+    case 'Tiled':   return tiledImage(img._3);
+    }
+}
+
+function plainImage(src) {
+    var img = newElement('img');
+    img.src = src;
+    img.name = src;
+    img.style.display = "block";
+    return img;
+}
+
+function tiledImage(src) {
+    var div = newElement('div');
+    div.style.backgroundImage = 'url(' + src + ')';
+    return div;
+}
+
+function fittedImage(w, h, src) {
+    var div = newElement('div');
+    div.style.background = 'url(' + src + ') no-repeat center';
+    div.style.webkitBackgroundSize = 'cover';
+    div.style.MozBackgroundSize = 'cover';
+    div.style.OBackgroundSize = 'cover';
+    div.style.backgroundSize = 'cover';
+    return div;
+}
+
+function croppedImage(elem, w, h, src) {
+    var pos = elem._0._0;
+    var e = newElement('div');
+    e.style.overflow = "hidden";
+
+    var img = newElement('img');
+    img.onload = function() {
+        var sw = w / elem._1, sh = h / elem._2;
+        img.style.width = ((this.width * sw)|0) + 'px';
+        img.style.height = ((this.height * sh)|0) + 'px';
+        img.style.marginLeft = ((- pos._0 * sw)|0) + 'px';
+        img.style.marginTop = ((- pos._1 * sh)|0) + 'px';
+    };
+    img.src = src;
+    img.name = src;
+    e.appendChild(img);
+    return e;
+}
+
+function goIn(e) { e.style.position = 'absolute'; return e; }
+function goDown(e) { return e }
+function goRight(e) { e.style.styleFloat = e.style.cssFloat = "left"; return e; }
+function flowWith(f, array) {
+    var container = newElement('div');
+    for (var i = array.length; i--; ) {
+        container.appendChild(f(render(array[i])));
+    }
+    return container;
+}
+
+function flow(dir,elist) {
+    var array = fromList(elist);
+    switch(dir.ctor) {
+    case "DDown":  array.reverse();
+    case "DUp":    return flowWith(goDown,array);
+    case "DRight": array.reverse();
+    case "DLeft":  return flowWith(goRight,array);
+    case "DOut":   array.reverse();
+    case "DIn":    return flowWith(goIn,array);
+    }
+}
+
+function toPos(pos) {
+    switch(pos.ctor) {
+    case "Absolute": return  pos._0 + "px";
+    case "Relative": return (pos._0 * 100) + "%";
+    }
+}
+
+function setPos(pos,w,h,e) {
+    e.style.position = 'absolute';
+    e.style.margin = 'auto';
+    var transform = '';
+    switch(pos.horizontal.ctor) {
+    case 'P': e.style.right = toPos(pos.x); break;
+    case 'Z': transform = 'translateX(' + ((-w/2)|0) + 'px) ';
+    case 'N': e.style.left = toPos(pos.x); break;
+    }
+    switch(pos.vertical.ctor) {
+    case 'N': e.style.bottom = toPos(pos.y); break;
+    case 'Z': transform += 'translateY(' + ((-h/2)|0) + 'px)';
+    case 'P': e.style.top = toPos(pos.y); break;
+    }
+    if (transform !== '') addTransform(e.style, transform);
+    return e;
+}
+
+function container(pos,elem) {
+    var e = render(elem);
+    setPos(pos, elem.props.width, elem.props.height, e);
+    var div = newElement('div');
+    div.style.position = 'relative';
+    div.style.overflow = 'hidden';
+    div.appendChild(e);
+    return div;
+}
+
+function rawHtml(html) {
+    var e = newElement('div');
+    e.innerHTML = html;
+    return e;
+}
+
+function render(elem) { return setProps(elem.props, makeElement(elem)); }
+function makeElement(e) {
+    var elem = e.element;
+    switch(elem.ctor) {
+    case 'Image':     return image(e.props, elem);
+    case 'Flow':      return flow(elem._0, elem._1);
+    case 'Container': return container(elem._0, elem._1);
+    case 'Spacer':    return newElement('div');
+    case 'RawHtml':   return rawHtml(elem._0);
+    case 'Custom':    return elem.render(elem.model);
+    }
+}
+
+function update(node, curr, next) {
+    if (node.tagName === 'A') { node = node.firstChild; }
+    if (curr.props.id === next.props.id) return updateProps(node, curr, next);
+    if (curr.element.ctor !== next.element.ctor) {
+        node.parentNode.replaceChild(render(next),node);
+        return true;
+    }
+    var nextE = next.element, currE = curr.element;
+    switch(nextE.ctor) {
+    case "Spacer": break;
+    case "RawHtml":
+        if (nextE._0 !== currE._0) node.innerHTML = nextE._0;
+        break;
+    case "Image":
+        if (nextE._0.ctor === 'Plain') {
+            if (nextE._3 !== currE._3) node.src = nextE._3;
+        } else if (!eq(nextE,currE) ||
+                   next.props.width !== curr.props.width ||
+                   next.props.height !== curr.props.height) {
+            node.parentNode.replaceChild(render(next),node);
+            return true;
+        }
+        break;
+    case "Flow":
+        var arr = fromList(nextE._1);
+        for (var i = arr.length; i--; ) { arr[i] = arr[i].element.ctor; }
+        if (nextE._0.ctor !== currE._0.ctor) {
+            node.parentNode.replaceChild(render(next),node);
+            return true;
+        }
+        var nexts = fromList(nextE._1);
+        var kids = node.childNodes;
+        if (nexts.length !== kids.length) {
+            node.parentNode.replaceChild(render(next),node);
+            return true;
+        }
+        var currs = fromList(currE._1);
+        var goDir = function(x) { return x; };
+        switch(nextE._0.ctor) {
+        case "DDown":  case "DUp":   goDir = goDown; break;
+        case "DRight": case "DLeft": goDir = goRight; break;
+        case "DOut":   case "DIn":   goDir = goIn; break;
+        }
+        for (var i = kids.length; i-- ;) {
+            update(kids[i],currs[i],nexts[i]);
+            goDir(kids[i]);
+        }
+        break;
+    case "Container":
+        var inner = node.firstChild;
+        if (!update(inner, currE._1, nextE._1)) {
+            if (nextE._0.horizontal.ctor !== currE._0.horizontal.ctor) {
+                inner.style.left = inner.style.right = 'none';
+                removeTransform(inner.style);
+            }
+            if (nextE._0.vertical.ctor !== currE._0.vertical.ctor) {
+                inner.style.top = inner.style.bottom = 'none';
+                removeTransform(inner.style);
+            }
+        }
+        setPos(nextE._0, nextE._1.props.width, nextE._1.props.height, inner);
+        break;
+    case "Custom":
+        if (currE.type === nextE.type) {
+            var done = nextE.update(node, currE.model, nextE.model);
+            if (done) return;
+        } else {
+            return node.parentNode.replaceChild(render(next), node);
+        }
+    }
+    updateProps(node, curr, next);
+}
+
+function updateProps(node, curr, next) {
+    var props = next.props, currP = curr.props, e = node;
+    if (props.width !== currP.width)   e.style.width  = (props.width |0) + 'px';
+    if (props.height !== currP.height) e.style.height = (props.height|0) + 'px';
+    if (props.opacity !== 1 && props.opacity !== currP.opacity) {
+        e.style.opacity = props.opacity;
+    }
+    var nextColor = (props.color.ctor === 'Just' ?
+                     extract(props.color._0) : 'transparent');
+    if (e.style.backgroundColor !== nextColor) {
+        e.style.backgroundColor = nextColor;
+    }
+    if (props.tag !== currP.tag) { e.id = props.tag; }
+    if (props.href !== currP.href) {
+        if (currP.href === '') {
+            var a = newElement('a');
+            a.href = props.href;
+            a.style.width = '100%';
+            a.style.height = '100%';
+            a.style.top = 0;
+            a.style.left = 0;
+            a.style.display = 'block';
+            a.style.position = 'absolute';
+            e.style.position = 'relative';
+            e.appendChild(a);
+        } else {
+            node.lastNode.href = props.href;
+        }
+    }
+}
+
+return { render:render, update:update };
+
+};
+ElmRuntime.Render.Utils = function() {
+'use strict';
+
+function newElement(elementType) {
+    var e = document.createElement(elementType);    
+    e.style.padding = "0";
+    e.style.margin = "0";
+    return e;
+}
+
+function addTo(container, elem) {
+    container.appendChild(elem);
+}
+
+function extract(c) {
+    if (c._3 === 1) { return 'rgb(' + c._0 + ',' + c._1 + ',' + c._2 + ')'; }
+    return 'rgba(' + c._0 + ',' + c._1 + ',' + c._2 + ',' + c._3 + ')';
+}
+
+function addTransform(style, trans) {
+  style.transform       = trans;
+  style.msTransform     = trans;
+  style.MozTransform    = trans;
+  style.webkitTransform = trans;
+  style.OTransform      = trans;
+}
+
+function removeTransform(style) {
+  style.transform       = 'none';
+  style.msTransform     = 'none';
+  style.MozTransform    = 'none';
+  style.webkitTransform = 'none';
+  style.OTransform      = 'none';
+}
+
+var List = Elm.Native.List({});
+
+return {addTo:addTo,
+	newElement:newElement,
+	extract : extract,
+	fromList: List.toArray,
+	fromString: function(s) { return List.toArray(s).join(''); },
+	toString: List.fromArray,
+	eq: Elm.Native.Utils({}).eq,
+	addTransform: addTransform,
+	removeTransform: removeTransform
+	};
+};
diff --git a/data/interfaces.data b/data/interfaces.data
new file mode 100644
Binary files /dev/null and b/data/interfaces.data differ
diff --git a/docs.json b/docs.json
deleted file mode 100644
--- a/docs.json
+++ /dev/null
@@ -1,2043 +0,0 @@
-{ "modules" : [
-    { "name" : "Window",
-      "values" : [
-        { "name" : "dimensions",
-          "type" : "Signal (Int,Int)",
-          "desc" : "The current dimensions of the window (i.e. the area viewable to the\nuser, not including scroll bars).\n"
-        },
-        { "name" : "width",
-          "type" : "Signal Int",
-          "desc" : "The current width of the window.\n"
-        },
-        { "name" : "height",
-          "type" : "Signal Int",
-          "desc" : "The current height of the window.\n"
-        }
-      ]
-    },
-    { "name" : "WebSocket",
-      "values" : [
-        { "name" : "connect",
-          "type" : "String -> Signal String -> Signal String",
-          "desc" : "Create a web-socket. The first argument is the URL of the desired\nweb-socket server. The input signal holds the outgoing messages,\nand the resulting signal contains the incoming ones.\n"
-        }
-      ]
-    },
-    { "name" : "Touch",
-      "values" : [
-        { "name" : "Touch",
-          "type" : "type Touch = { x:Int, y:Int, id:Int, x0:Int, y0:Int, t0:Time }",
-          "desc" : "Every `Touch` has `xy` coordinates. It also has an identifier `id` to\ndistinguish one touch from another.\n\nA touch also keeps info about the intial point and time of contact:\n`x0`, `y0`, and `t0`. This helps compute more complicated gestures\nlike taps, drags, and swipes which need to know about timing or direction.\n"
-        },
-        { "name" : "touches",
-          "type" : "Signal [Touch]",
-          "desc" : "A list of ongoing touches.\n"
-        },
-        { "name" : "taps",
-          "type" : "Signal { x:Int, y:Int }",
-          "desc" : "The last position that was tapped. Default value is `{x=0,y=0}`.\nUpdates whenever the user taps the screen.\n"
-        }
-      ]
-    },
-    { "name" : "Time",
-      "values" : [
-        { "name" : "Time",
-          "type" : "type Time = Float",
-          "desc" : "Type alias to make it clearer when you are working with time values.\nUsing the `Time` constants instead of raw numbers is very highly recommended.\n"
-        },
-        { "name" : "millisecond",
-          "type" : "Time",
-          "desc" : "Units of time, making it easier to specify things like a\nhalf-second `(500 * milliseconds)` without remembering Elm&rsquo;s\nunderlying units of time.\n"
-        },
-        { "name" : "second",
-          "type" : "Time",
-          "desc" : ""
-        },
-        { "name" : "minute",
-          "type" : "Time",
-          "desc" : ""
-        },
-        { "name" : "hour",
-          "type" : "Time",
-          "desc" : ""
-        },
-        { "name" : "inMilliseconds",
-          "type" : "Time -> Float",
-          "desc" : ""
-        },
-        { "name" : "inSeconds",
-          "type" : "Time -> Float",
-          "desc" : ""
-        },
-        { "name" : "inMinutes",
-          "type" : "Time -> Float",
-          "desc" : ""
-        },
-        { "name" : "inHours",
-          "type" : "Time -> Float",
-          "desc" : ""
-        },
-        { "name" : "fps",
-          "type" : "Number a -> Signal Time",
-          "desc" : "Takes desired number of frames per second (fps). The resulting signal\ngives a sequence of time deltas as quickly as possible until it reaches\nthe desired FPS. A time delta is the time between the last frame and the\ncurrent frame.\n"
-        },
-        { "name" : "fpsWhen",
-          "type" : "Number a -> Signal Bool -> Signal Time",
-          "desc" : "Same as the fps function, but you can turn it on and off. Allows you\nto do brief animations based on user input without major inefficiencies.\nThe first time delta after a pause is always zero, no matter how long\nthe pause was. This way summing the deltas will actually give the amount\nof time that the output signal has been running.\n"
-        },
-        { "name" : "every",
-          "type" : "Time -> Signal Time",
-          "desc" : "Takes a time interval t. The resulting signal is the current time,\nupdated every t.\n"
-        },
-        { "name" : "since",
-          "type" : "Time -> Signal a -> Signal Bool",
-          "desc" : "Takes a time `t` and any signal. The resulting boolean signal\nis true for time `t` after every event on the input signal.\nSo ``(second `since` Mouse.clicks)`` would result in a signal\nthat is true for one second after each mouse click and false\notherwise.\n"
-        },
-        { "name" : "timestamp",
-          "type" : "Signal a -> Signal (Time, a)",
-          "desc" : "Add a timestamp to any signal. Timestamps increase monotonically. Each\ntimestamp is related to a specfic event, so `Mouse.x` and `Mouse.y` will\nalways have the same timestamp because they both rely on the same\nunderlying event.\n"
-        },
-        { "name" : "delay",
-          "type" : "Time -> Signal a -> Signal a",
-          "desc" : "Delay a signal by a certain amount of time. So `(delay second Mouse.clicks)`\nwill update one second later than any mouse click.\n"
-        }
-      ]
-    },
-    { "name" : "Text",
-      "values" : [
-        { "name" : "toText",
-          "type" : "String -> Text",
-          "desc" : "Convert a string into text which can be styled and displayed.\n"
-        },
-        { "name" : "typeface",
-          "type" : "String -> Text -> Text",
-          "desc" : "Set the typeface of some text. The first argument should be a comma separated listing of the desired typefaces\n    \"helvetica, arial, sans-serif\"\nWorks the same as the CSS font-family property.\n"
-        },
-        { "name" : "monospace",
-          "type" : "Text -> Text",
-          "desc" : "Switch to a monospace typeface. Good for code snippets.\n"
-        },
-        { "name" : "header",
-          "type" : "Text -> Text",
-          "desc" : "Make text big and noticable.\n"
-        },
-        { "name" : "link",
-          "type" : "String -> Text -> Text",
-          "desc" : "Create a link.\n"
-        },
-        { "name" : "height",
-          "type" : "Float -> Text -> Text",
-          "desc" : "Set the height of text in \\\"ems\\\". 1em is the normal height of text. 2ems is twice that height.\n"
-        },
-        { "name" : "color",
-          "type" : "Color -> Text -> Text",
-          "desc" : "Set the color of a string.\n"
-        },
-        { "name" : "bold",
-          "type" : "Text -> Text",
-          "desc" : "Make a string bold.\n"
-        },
-        { "name" : "italic",
-          "type" : "Text -> Text",
-          "desc" : "Italicize a string.\n"
-        },
-        { "name" : "overline",
-          "type" : "Text -> Text",
-          "desc" : "Draw a line above a string.\n"
-        },
-        { "name" : "underline",
-          "type" : "Text -> Text",
-          "desc" : "Underline a string.\n"
-        },
-        { "name" : "strikeThrough",
-          "type" : "Text -> Text",
-          "desc" : "Draw a line through a string.\n"
-        },
-        { "name" : "justified",
-          "type" : "Text -> Element",
-          "desc" : "Display justified, styled text.\n"
-        },
-        { "name" : "centered",
-          "type" : "Text -> Element",
-          "desc" : "Display centered, styled text.\n"
-        },
-        { "name" : "righted",
-          "type" : "Text -> Element",
-          "desc" : "Display right justified, styled text.\n"
-        },
-        { "name" : "text",
-          "type" : "Text -> Element",
-          "desc" : "Display styled text.\n"
-        },
-        { "name" : "plainText",
-          "type" : "String -> Element",
-          "desc" : "Display a plain string.\n"
-        },
-        { "name" : "asText",
-          "type" : "a -> Element",
-          "desc" : "Convert anything to it's textual representation and make it displayable in browser\n\n    asText == text . monospace . show\n\nExcellent for debugging.\n"
-        }
-      ]
-    },
-    { "name" : "Signal",
-      "values" : [
-        { "name" : "constant",
-          "type" : "a -> Signal a",
-          "desc" : "Create a constant signal that never changes.\n"
-        },
-        { "name" : "lift",
-          "type" : "(a -> b) -> Signal a -> Signal b",
-          "desc" : "Transform a signal with a given function.\n"
-        },
-        { "name" : "lift2",
-          "type" : "(a -> b -> c) -> Signal a -> Signal b -> Signal c",
-          "desc" : "Combine two signals with a given function.\n"
-        },
-        { "name" : "lift3",
-          "type" : "(a -> b -> c -> d) -> Signal a -> Signal b -> Signal c -> Signal d",
-          "desc" : "Combine three signals with a given function.\n"
-        },
-        { "name" : "lift4",
-          "type" : "(a -> b -> c -> d -> e) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e",
-          "desc" : ""
-        },
-        { "name" : "lift5",
-          "type" : "(a -> b -> c -> d -> e -> f) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f",
-          "desc" : ""
-        },
-        { "name" : "lift6",
-          "type" : "(a -> b -> c -> d -> e -> f -> g)\n      -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal g",
-          "desc" : ""
-        },
-        { "name" : "lift7",
-          "type" : "(a -> b -> c -> d -> e -> f -> g -> h)\n      -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal g -> Signal h",
-          "desc" : ""
-        },
-        { "name" : "lift8",
-          "type" : "(a -> b -> c -> d -> e -> f -> g -> h -> i)\n      -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal g -> Signal h -> Signal i",
-          "desc" : ""
-        },
-        { "name" : "foldp",
-          "type" : "(a -> b -> b) -> b -> Signal a -> Signal b",
-          "desc" : "Create a past-dependent signal. Each value given on the input signal will\nbe accumulated, producing a new output value.\n\nFor instance, `(foldp (\\\\t acc -> acc + 1) 0 (Time.every second))` increments every second.\n"
-        },
-        { "name" : "merge",
-          "type" : "Signal a -> Signal a -> Signal a",
-          "desc" : "Merge two signals into one, biased towards the first signal if both signals\nupdate at the same time.\n"
-        },
-        { "name" : "merges",
-          "type" : "[Signal a] -> Signal a",
-          "desc" : "Merge many signals into one, biased towards the left-most signal if multiple\nsignals update simultaneously.\n"
-        },
-        { "name" : "combine",
-          "type" : "[Signal a] -> Signal [a]",
-          "desc" : "Combine a list of signals into a signal of lists.\n"
-        },
-        { "name" : "count",
-          "type" : "Signal a -> Signal Int",
-          "desc" : "Count the number of events that have occured.\n"
-        },
-        { "name" : "countIf",
-          "type" : "(a -> Bool) -> Signal a -> Signal Int",
-          "desc" : "Count the number of events that have occured that satisfy a given predicate.\n"
-        },
-        { "name" : "keepIf",
-          "type" : "(a -> Bool) -> a -> Signal a -> Signal a",
-          "desc" : "Keep only events that satisfy the given predicate. Elm does not allow\nundefined signals, so a base case must be provided in case the predicate is\nnever satisfied.\n"
-        },
-        { "name" : "dropIf",
-          "type" : "(a -> Bool) -> a -> Signal a -> Signal a",
-          "desc" : "Drop events that satisfy the given predicate. Elm does not allow undefined\nsignals, so a base case must be provided in case the predicate is never\nsatisfied.\n"
-        },
-        { "name" : "keepWhen",
-          "type" : "Signal Bool -> a -> Signal a -> Signal a",
-          "desc" : "Keep events only when the first signal is true. When the first signal becomes\ntrue, the most recent value of the second signal will be propagated. Until\nthe first signal becomes false again, all events will be propagated. Elm does\nnot allow undefined signals, so a base case must be provided in case the first\nsignal is never true.\n"
-        },
-        { "name" : "dropWhen",
-          "type" : "Signal Bool -> a -> Signal a -> Signal a",
-          "desc" : "Drop events when the first signal is true. When the first signal becomes false,\nthe most recent value of the second signal will be propagated. Until the first\nsignal becomes true again, all events will be propagated. Elm does not allow\nundefined signals, so a base case must be provided in case the first signal is\nalways true.\n"
-        },
-        { "name" : "dropRepeats",
-          "type" : "Signal a -> Signal a",
-          "desc" : "Drop sequential repeated values. For example, if a signal produces the\nsequence `[1,1,2,2,1]`, it becomes `[1,2,1]` by dropping the values that\nare the same as the previous value.\n"
-        },
-        { "name" : "sampleOn",
-          "type" : "Signal a -> Signal b -> Signal b",
-          "desc" : "Sample from the second input every time an event occurs on the first input.\nFor example, `(sampleOn clicks (every second))` will give the approximate\ntime of the latest click.\n"
-        },
-        { "name" : "<~",
-          "type" : "(a -> b) -> Signal a -> Signal b",
-          "desc" : "An alias for `lift`. A prettier way to apply a\nfunction to the current value of a signal.\n\n        lift f signal == f <~ signal\n"
-        },
-        { "name" : "~",
-          "type" : "Signal (a -> b) -> Signal a -> Signal b",
-          "desc" : "Signal application. This takes two signals, holding a function and\na value. It applies the current function to the current value.\n\nSo the following expressions are equivalent:\n\n        scene <~ Window.dimensions ~ Mouse.position\n        lift2 scene Window.dimensions Mouse.position\n"
-        }
-      ]
-    },
-    { "name" : "Set",
-      "values" : [
-        { "name" : "empty",
-          "type" : "Set (Comparable k)",
-          "desc" : "Create an empty set.\n"
-        },
-        { "name" : "singleton",
-          "type" : "Comparable k -> Set (Comparable k)",
-          "desc" : "Create a set with one value.\n"
-        },
-        { "name" : "insert",
-          "type" : "Comparable k -> Set (Comparable k) -> Set (Comparable k)",
-          "desc" : "Insert a value into a set.\n"
-        },
-        { "name" : "remove",
-          "type" : "Comparable k -> Set (Comparable k) -> Set (Comparable k)",
-          "desc" : "Remove a value from a set. If the value is not found, no changes are made.\n"
-        },
-        { "name" : "member",
-          "type" : "Comparable k -> Set (Comparable k) -> Bool",
-          "desc" : "Determine if a value is in a set.\n"
-        },
-        { "name" : "union",
-          "type" : "Set (Comparable k) -> Set (Comparable k) -> Set (Comparable k)",
-          "desc" : "Get the union of two sets. Keep all values.\n"
-        },
-        { "name" : "intersect",
-          "type" : "Set (Comparable k) -> Set (Comparable k) -> Set (Comparable k)",
-          "desc" : "Get the intersection of two sets. Keeps values that appear in both sets.\n"
-        },
-        { "name" : "diff",
-          "type" : "Set (Comparable k) -> Set (Comparable k) -> Set (Comparable k)",
-          "desc" : "Get the difference between the first set and the second. Keeps values\nthat do not appear in the second set.\n"
-        },
-        { "name" : "toList",
-          "type" : "Set (Comparable k) -> [Comparable k]",
-          "desc" : "Convert a set into a list.\n"
-        },
-        { "name" : "fromList",
-          "type" : "[Comparable k] -> Set (Comparable k)",
-          "desc" : "Convert a list into a set, removing any duplicates.\n"
-        },
-        { "name" : "foldl",
-          "type" : "(Comparable a -> b -> b) -> b -> Set (Comparable a) -> b",
-          "desc" : "Fold over the values in a set, in order from lowest to highest.\n"
-        },
-        { "name" : "foldr",
-          "type" : "(Comparable a -> b -> b) -> b -> Set (Comparable a) -> b",
-          "desc" : "Fold over the values in a set, in order from highest to lowest.\n"
-        },
-        { "name" : "map",
-          "type" : "(Comparable a -> Comparable b) -> Set (Comparable a) -> Set (Comparable b)",
-          "desc" : "Map a function onto a set, creating a new set with no duplicates.\n"
-        }
-      ]
-    },
-    { "name" : "Random",
-      "values" : [
-        { "name" : "range",
-          "type" : "Int -> Int -> Signal a -> Signal Int",
-          "desc" : "Given a range from low to high and a signal of values, this produces\na new signal that changes whenever the input signal changes. The new\nvalues are random number between 'low' and 'high' inclusive.\n"
-        },
-        { "name" : "float",
-          "type" : "Signal a -> Signal Float",
-          "desc" : "Produces a new signal that changes whenever the input signal changes.\nThe new values are random numbers in [0..1).\n"
-        }
-      ]
-    },
-    { "name" : "Prelude",
-      "values" : [
-        { "name" : "radians",
-          "type" : "Float -> Float",
-          "desc" : "Convert radians to standard Elm angles (radians).\n"
-        },
-        { "name" : "degrees",
-          "type" : "Float -> Float",
-          "desc" : "Convert degrees to standard Elm angles (radians).\n"
-        },
-        { "name" : "turns",
-          "type" : "Float -> Float",
-          "desc" : "Convert turns to standard Elm angles (radians).\nOne turn is equal to 360&deg;.\n"
-        },
-        { "name" : "fromPolar",
-          "type" : "(Float,Float) -> (Float,Float)",
-          "desc" : "Start with polar coordinates (r,&theta;)\nand get out cartesian coordinates (x,y).\n"
-        },
-        { "name" : "toPolar",
-          "type" : "(Float,Float) -> (Float,Float)",
-          "desc" : "Start with cartesian coordinates (x,y)\nand get out polar coordinates (r,&theta;).\n"
-        },
-        { "name" : "+",
-          "type" : "Number a -> Number a -> Number a",
-          "desc" : ""
-        },
-        { "name" : "-",
-          "type" : "Number a -> Number a -> Number a",
-          "desc" : ""
-        },
-        { "name" : "*",
-          "type" : "Number a -> Number a -> Number a",
-          "desc" : ""
-        },
-        { "name" : "/",
-          "type" : "Float -> Float -> Float",
-          "desc" : "Floating point division.\n"
-        },
-        { "name" : "div",
-          "type" : "Int -> Int -> Int",
-          "desc" : "Integer division, remainder is discarded.\n"
-        },
-        { "name" : "rem",
-          "type" : "Int -> Int -> Int",
-          "desc" : "Finds the remainder after dividing one number by another: ``4 `rem` 3 == 1``\n"
-        },
-        { "name" : "mod",
-          "type" : "Int -> Int -> Int",
-          "desc" : "Perform modular arithmetic: ``7 `mod` 2 == 1``\n"
-        },
-        { "name" : "^",
-          "type" : "Number a -> Number a -> Number a",
-          "desc" : "Exponentiation: `3^2 == 9`\n"
-        },
-        { "name" : "cos",
-          "type" : "Float -> Float",
-          "desc" : ""
-        },
-        { "name" : "sin",
-          "type" : "Float -> Float",
-          "desc" : ""
-        },
-        { "name" : "tan",
-          "type" : "Float -> Float",
-          "desc" : ""
-        },
-        { "name" : "acos",
-          "type" : "Float -> Float",
-          "desc" : ""
-        },
-        { "name" : "asin",
-          "type" : "Float -> Float",
-          "desc" : ""
-        },
-        { "name" : "atan",
-          "type" : "Float -> Float",
-          "desc" : "You probably do not want to use this. Because it takes `(y/x)` as the argument\nthere is no way to know where the negative signs come from so the resulting\nangle is always between &pi;/2 and -&pi;/2 (in quadrants I and IV).\n"
-        },
-        { "name" : "atan2",
-          "type" : "Float -> Float -> Float",
-          "desc" : "This helps you find the angle of a cartesian coordinate.\nYou will almost certainly want to use this instead of `atan`.\nSo `atan2 y x` computes *atan(y/x)* but also keeps track of which\nquadrant the angle should really be in. The result will be between\n&pi; and -&pi;, giving you the full range of angles.\n"
-        },
-        { "name" : "sqrt",
-          "type" : "Number a -> Number a",
-          "desc" : "Take the square root of a number.\n"
-        },
-        { "name" : "abs",
-          "type" : "Number a -> Number a",
-          "desc" : "Take the absolute value of a number.\n"
-        },
-        { "name" : "logBase",
-          "type" : "Number a -> Number a -> Number a",
-          "desc" : "Calculate the logarithm of a number with a given base: `logBase 10 100 == 2`\n"
-        },
-        { "name" : "min",
-          "type" : "Number a -> Number a -> Number a",
-          "desc" : "Given two numbers, returns the smaller one.\n"
-        },
-        { "name" : "max",
-          "type" : "Number a -> Number a -> Number a",
-          "desc" : "Given two numbers, returns the larger one.\n"
-        },
-        { "name" : "clamp",
-          "type" : "Number a -> Number a -> Number a -> Number a",
-          "desc" : "Clamps a number within a given range. With the expression `clamp 100 200 x`\nthe results are as follows:\n\n  * `100   if x < 100`\n  * ` x    if 100 <= x < 200`\n  * `200   if 200 <= x`\n"
-        },
-        { "name" : "pi",
-          "type" : "Float",
-          "desc" : "An approximation of pi.\n"
-        },
-        { "name" : "e",
-          "type" : "Float",
-          "desc" : "An approximation of e.\n"
-        },
-        { "name" : "==",
-          "type" : "a -> a -> Bool",
-          "desc" : "Compare any two values for structural equality. Functions cannot be compared.\n"
-        },
-        { "name" : "/=",
-          "type" : "a -> a -> Bool",
-          "desc" : ""
-        },
-        { "name" : "<",
-          "type" : "Comparable a -> Comparable a -> Bool",
-          "desc" : ""
-        },
-        { "name" : ">",
-          "type" : "Comparable a -> Comparable a -> Bool",
-          "desc" : ""
-        },
-        { "name" : "<=",
-          "type" : "Comparable a -> Comparable a -> Bool",
-          "desc" : ""
-        },
-        { "name" : ">=",
-          "type" : "Comparable a -> Comparable a -> Bool",
-          "desc" : ""
-        },
-        { "name" : "compare",
-          "type" : "Comparable a -> Comparable a -> Order",
-          "desc" : "Compare any two comparable values. Comparable values include `String`, `Char`,\n`Int`, `Float`, `Time`, or a list or tuple containing comparable values.\nThese are also the only values that work as `Dict` keys or `Set` members.\n"
-        },
-        { "name" : "LT",
-          "type" : "Order",
-          "desc" : ""
-        },
-        { "name" : "EQ",
-          "type" : "Order",
-          "desc" : ""
-        },
-        { "name" : "GT",
-          "type" : "Order",
-          "desc" : ""
-        },
-        { "name" : "Order",
-          "type" : "data Order = LT | EQ | GT",
-          "desc" : "Represents the relative ordering of two things.\nThe relations are less than, equal to, and greater than.\n"
-        },
-        { "name" : "&&",
-          "type" : "Bool -> Bool -> Bool",
-          "desc" : "The and operator. True if both inputs are True.\n"
-        },
-        { "name" : "||",
-          "type" : "Bool -> Bool -> Bool",
-          "desc" : "The or operator. True if one or both inputs are True.\n"
-        },
-        { "name" : "xor",
-          "type" : "Bool -> Bool -> Bool",
-          "desc" : "The exclusive-or operator. True if exactly one input is True.\n"
-        },
-        { "name" : "not",
-          "type" : "Bool -> Bool",
-          "desc" : "Negate a boolean value: `(not True == False)` and `(not False == True)`\n"
-        },
-        { "name" : "otherwise",
-          "type" : "Bool",
-          "desc" : "Equal to true. Useful as the last case of a multi-way-if.\n"
-        },
-        { "name" : "round",
-          "type" : "Float -> Int",
-          "desc" : "Round a number to the nearest integer.\n"
-        },
-        { "name" : "truncate",
-          "type" : "Float -> Int",
-          "desc" : "Truncate a decimal number, rounding towards zero.\n"
-        },
-        { "name" : "floor",
-          "type" : "Float -> Int",
-          "desc" : "Floor function, rounding down.\n"
-        },
-        { "name" : "ceiling",
-          "type" : "Float -> Int",
-          "desc" : "Ceiling function, rounding up.\n"
-        },
-        { "name" : "toFloat",
-          "type" : "Int -> Float",
-          "desc" : "Convert an integer into a float.\n"
-        },
-        { "name" : "show",
-          "type" : "a -> String",
-          "desc" : "Convert almost any value to its string representation.\n"
-        },
-        { "name" : "readInt",
-          "type" : "String -> Maybe Int",
-          "desc" : "Read an integer from a string\n"
-        },
-        { "name" : "readFloat",
-          "type" : "String -> Maybe Float",
-          "desc" : "Read a float from a string.\n"
-        },
-        { "name" : ".",
-          "type" : "(b -> c) -> (a -> b) -> (a -> c)",
-          "desc" : "Function composition: `(f . g == (\\\\x -> f (g x)))`\n"
-        },
-        { "name" : "|>",
-          "type" : "a -> (a -> b) -> b",
-          "desc" : "Forward function application `x |> f == f x`. This function is useful\nfor avoiding parenthesis and writing code in a more natural way.\nConsider the following code to create a pentagon:\n\n        scale 2 (move (10,10) (filled blue (ngon 5 30)))\n\nThis can also be written as:\n\n        ngon 5 30 |> filled blue\n                  |> move (10,10)\n                  |> scale 2\n"
-        },
-        { "name" : "<|",
-          "type" : "(a -> b) -> a -> b",
-          "desc" : "Function application `f <| x == f x`. This function is useful for avoiding\nparenthesis. Consider the following code to create a text element:\n\n        text (monospace (toText \"code\"))\n\nThis can also be written as:\n\n        text . monospace <| toText \"code\"\n"
-        },
-        { "name" : "id",
-          "type" : "a -> a",
-          "desc" : "Given a value, returns exactly the same value.\n"
-        },
-        { "name" : "fst",
-          "type" : "(a,b) -> a",
-          "desc" : "Given a 2-tuple, returns the first value.\n"
-        },
-        { "name" : "snd",
-          "type" : "(a,b) -> b",
-          "desc" : "Given a 2-tuple, returns the second value.\n"
-        },
-        { "name" : "flip",
-          "type" : "(a -> b -> c) -> (b -> a -> c)",
-          "desc" : "Flips the order of the first two arguments to a function.\n"
-        },
-        { "name" : "curry",
-          "type" : "((a,b) -> c) -> a -> b -> c",
-          "desc" : "Change how arguments are passed to a function. This splits paired arguments\ninto two separate arguments.\n"
-        },
-        { "name" : "uncurry",
-          "type" : "(a -> b -> c) -> (a,b) -> c",
-          "desc" : "Change how arguments are passed to a function. This combines two arguments\ninto a sigle pair.\n"
-        }
-      ]
-    },
-    { "name" : "Mouse",
-      "values" : [
-        { "name" : "position",
-          "type" : "Signal (Int,Int)",
-          "desc" : "The current mouse position.\n"
-        },
-        { "name" : "x",
-          "type" : "Signal Int",
-          "desc" : "The current x-coordinate of the mouse.\n"
-        },
-        { "name" : "y",
-          "type" : "Signal Int",
-          "desc" : "The current y-coordinate of the mouse.\n"
-        },
-        { "name" : "isDown",
-          "type" : "Signal Bool",
-          "desc" : "The current state of the left mouse-button.\nTrue when the button is down, and false otherwise.\n"
-        },
-        { "name" : "isClicked",
-          "type" : "Signal Bool",
-          "desc" : "True immediately after the left mouse-button has been clicked,\nand false otherwise.\n"
-        },
-        { "name" : "clicks",
-          "type" : "Signal ()",
-          "desc" : "Always equal to unit. Event triggers on every mouse click.\n"
-        }
-      ]
-    },
-    { "name" : "Maybe",
-      "values" : [
-        { "name" : "Just",
-          "type" : "t1 -> Maybe t1",
-          "desc" : ""
-        },
-        { "name" : "Nothing",
-          "type" : "Maybe t1",
-          "desc" : ""
-        },
-        { "name" : "Maybe",
-          "type" : "data Maybe a = Just a | Nothing",
-          "desc" : "The Maybe datatype. Useful when a computation may or may not\nresult in a value (e.g. logarithm is defined only for positive numbers).\n"
-        },
-        { "name" : "maybe",
-          "type" : "b -> (a -> b) -> Maybe a -> b",
-          "desc" : "Apply a function to the contents of a `Maybe`.\nReturn default when given `Nothing`.\n"
-        },
-        { "name" : "isJust",
-          "type" : "Maybe a -> Bool",
-          "desc" : "Check if constructed with `Just`.\n"
-        },
-        { "name" : "isNothing",
-          "type" : "Maybe a -> Bool",
-          "desc" : "Check if constructed with `Nothing`.\n"
-        },
-        { "name" : "cons",
-          "type" : "Maybe a -> [a] -> [a]",
-          "desc" : "If `Just`, adds the value to the front of the list.\nIf `Nothing`, list is unchanged.\n"
-        },
-        { "name" : "justs",
-          "type" : "[Maybe a] -> [a]",
-          "desc" : "Filters out Nothings and extracts the remaining values.\n"
-        }
-      ]
-    },
-    { "name" : "Matrix2D",
-      "values" : [
-        { "name" : "identity",
-          "type" : "Matrix2D",
-          "desc" : "Create an identity matrix.\n\n          / 1 0 \\\\\n          \\\\ 0 1 /\n"
-        },
-        { "name" : "matrix",
-          "type" : "Float -> Float -> Float -> Float -> Float -> Float -> Matrix2D",
-          "desc" : "Creates an arbitrary matrix. This lets you create scales, shears, reflections,\ntranslations, or any other 2D transform.\n\n      matrix a b c d dx dy\n\n          / a b \\\\\n          \\\\ c d /\n\nAnd `dx` and `dy` are the translation values.\n"
-        },
-        { "name" : "rotation",
-          "type" : "Float -> Matrix2D",
-          "desc" : "Creates a [rotation matrix](http://en.wikipedia.org/wiki/Rotation_matrix).\nGiven an angle t, it creates a counterclockwise rotation matrix:\n\n          / cos t  -sin t \\\\\n          \\\\ sin t   cos t /\n"
-        },
-        { "name" : "multiply",
-          "type" : "Matrix2D -> Matrix2D -> Matrix2D",
-          "desc" : "Multiplies two matrices together:\n\n      multiply a b\n\n          / a11 a12 \\\\  .  / b11 b12 \\\\\n          \\\\ a21 a22 /     \\\\ b21 b22 /\n"
-        }
-      ]
-    },
-    { "name" : "List",
-      "values" : [
-        { "name" : "::",
-          "type" : "a -> [a] -> [a]",
-          "desc" : "Add an element to the front of a list `(1 :: [2,3] == [1,2,3])`\n"
-        },
-        { "name" : "++",
-          "type" : "Appendable a -> Appendable a -> Appendable a",
-          "desc" : "Puts two appendable things together:\n\n        [1,1] ++ [2,3] == [1,1,2,3]\n        \"abc\" ++ \"123\" == \"abc123\"\n"
-        },
-        { "name" : "head",
-          "type" : "[a] -> a",
-          "desc" : "Extract the first element of a list. List must be non-empty.\n`(head [1,2,3] == 1)`\n"
-        },
-        { "name" : "tail",
-          "type" : "[a] -> [a]",
-          "desc" : "Extract the elements after the head of the list. List must be non-empty.\n `(tail [1,2,3] == [2,3])`\n"
-        },
-        { "name" : "last",
-          "type" : "[a] -> a",
-          "desc" : "Extract the last element of a list. List must be non-empty.\n`(last [1,2,3] == 3)`\n"
-        },
-        { "name" : "map",
-          "type" : "(a -> b) -> [a] -> [b]",
-          "desc" : "Apply a function to every element of a list: `(map sqrt [1,4,9] == [1,2,3])`\n"
-        },
-        { "name" : "foldl",
-          "type" : "(a -> b -> b) -> b -> [a] -> b",
-          "desc" : "Reduce a list from the left: `(foldl (::) [] \"gateman\" == \"nametag\")`\n"
-        },
-        { "name" : "foldr",
-          "type" : "(a -> b -> b) -> b -> [a] -> b",
-          "desc" : "Reduce a list from the right: `(foldr (+) 0 [1,2,3] == 6)`\n"
-        },
-        { "name" : "foldl1",
-          "type" : "(a -> a -> a) -> [a] -> a",
-          "desc" : "Reduce a list from the left without a base case. List must be non-empty.\n"
-        },
-        { "name" : "foldr1",
-          "type" : "(a -> a -> a) -> [a] -> a",
-          "desc" : "Reduce a list from the right without a base case. List must be non-empty.\n"
-        },
-        { "name" : "scanl",
-          "type" : "(a -> b -> b) -> b -> [a] -> [b]",
-          "desc" : "Reduce a list from the left, building up all of the intermediate results into a list.\n\n        scanl (+) 0 [1,2,3,4] == [0,1,3,6,10]\n"
-        },
-        { "name" : "scanl1",
-          "type" : "(a -> a -> a) -> [a] -> [a]",
-          "desc" : "Same as scanl but it doesn't require a base case. List must be non-empty.\n\n        scanl1 (+) [1,2,3,4] == [1,3,6,10]\n"
-        },
-        { "name" : "filter",
-          "type" : "(a -> Bool) -> [a] -> [a]",
-          "desc" : "Filter out elements which do not satisfy the predicate: `(filter isLower \"AaBbCc\" == \"abc\")`\n"
-        },
-        { "name" : "length",
-          "type" : "[a] -> Int",
-          "desc" : "Determine the length of a list: `(length \"innumerable\" == 11)`\n"
-        },
-        { "name" : "reverse",
-          "type" : "[a] -> [a]",
-          "desc" : "Reverse a list. `(reverse [1..4] == [4,3,2,1])`\n"
-        },
-        { "name" : "all",
-          "type" : "(a -> Bool) -> [a] -> Bool",
-          "desc" : "Check to see if all elements satisfy the predicate.\n"
-        },
-        { "name" : "any",
-          "type" : "(a -> Bool) -> [a] -> Bool",
-          "desc" : "Check to see if any elements satisfy the predicate.\n"
-        },
-        { "name" : "and",
-          "type" : "[Bool] -> Bool",
-          "desc" : "Check to see if all elements are True.\n"
-        },
-        { "name" : "or",
-          "type" : "[Bool] -> Bool",
-          "desc" : "Check to see if any elements are True.\n"
-        },
-        { "name" : "concat",
-          "type" : "[Appendable a] -> Appendable a",
-          "desc" : "Concatenate a list of appendable things:\n\n        concat [\"tree\",\"house\"] == \"treehouse\"\n"
-        },
-        { "name" : "concatMap",
-          "type" : "(a -> Appendable b) -> [a] -> Appendable b",
-          "desc" : "Map a given function onto a list and flatten the resulting lists.\n\n        concatMap f xs == concat (map f xs)\n"
-        },
-        { "name" : "sum",
-          "type" : "[Number a] -> Number a",
-          "desc" : "Get the sum of the list elements. `(sum [1..4] == 10)`\n"
-        },
-        { "name" : "product",
-          "type" : "[Number a] -> Number a",
-          "desc" : "Get the product of the list elements. `(product [1..4] == 24)`\n"
-        },
-        { "name" : "maximum",
-          "type" : "[Number a] -> Number a",
-          "desc" : "Find the highest number in a non-empty list.\n"
-        },
-        { "name" : "minimum",
-          "type" : "[Number a] -> Number a",
-          "desc" : "Find the lowest number in a non-empty list.\n"
-        },
-        { "name" : "partition",
-          "type" : "(a -> Bool) -> [a] -> ([a],[a])",
-          "desc" : "Split a list based on the predicate.\n"
-        },
-        { "name" : "zip",
-          "type" : "[a] -> [b] -> [(a,b)]",
-          "desc" : "Combine two lists, combining them into tuples pairwise.\nIf one list is longer, the extra elements are dropped.\n\n        zip [1,2,3] [6,7] == [(1,6),(2,7)]\n        zip == zipWith (,)\n"
-        },
-        { "name" : "zipWith",
-          "type" : "(a -> b -> c) -> [a] -> [b] -> [c]",
-          "desc" : "Combine two lists, combining them with the given function.\nIf one list is longer, the extra elements are dropped.\n\n        zipWith (+) [1,2,3] [1,2,3,4] == [2,4,6]\n"
-        },
-        { "name" : "unzip",
-          "type" : "[(a,b)] -> ([a],[b])",
-          "desc" : "Decompose a list of tuples.\n"
-        },
-        { "name" : "split",
-          "type" : "[a] -> [a] -> [[a]]",
-          "desc" : "Split a list with a given seperator.\n\n        split \",\" \"hello,there,friend\" == [\"hello\", \"there\", \"friend\"]\n"
-        },
-        { "name" : "join",
-          "type" : "Appendable a -> [Appendable a] -> Appendable a",
-          "desc" : "Places the given value between all of the lists in the second argument\nand concatenates the result. \n\n        join \"a\" [\"H\",\"w\",\"ii\",\"n\"] == \"Hawaiian\"\n"
-        },
-        { "name" : "intersperse",
-          "type" : "a -> [a] -> [a]",
-          "desc" : "Places the given value between all members of the given list.\n\n        intersperse ' ' \"INCEPTION\" == \"I N C E P T I O N\"\n"
-        },
-        { "name" : "take",
-          "type" : "Int -> [a] -> [a]",
-          "desc" : "Take the first n members of a list: `(take 2 [1,2,3,4] == [1,2])`\n"
-        },
-        { "name" : "drop",
-          "type" : "Int -> [a] -> [a]",
-          "desc" : "Drop the first n members of a list: `(drop 2 [1,2,3,4] == [3,4])`\n"
-        }
-      ]
-    },
-    { "name" : "Keyboard",
-      "values" : [
-        { "name" : "KeyCode",
-          "type" : "type KeyCode = Int",
-          "desc" : "Type alias to make it clearer what integers are supposed to represent\nin this library. Use [`Char.toCode`](docs/Char.elm#toCode) and\n[`Char.fromCode`](/docs/Char.elm#fromCode) to convert key codes to characters.\n"
-        },
-        { "name" : "arrows",
-          "type" : "Signal { x:Int, y:Int }",
-          "desc" : "A signal of records indicating which arrow keys are pressed.\n\n`{ x = 0, y = 0 }` when pressing no arrows.<br>\n`{ x =-1, y = 0 }` when pressing the left arrow.<br>\n`{ x = 1, y = 1 }` when pressing the up and right arrows.<br>\n`{ x = 0, y =-1 }` when pressing the down, left, and right arrows.\n"
-        },
-        { "name" : "wasd",
-          "type" : "Signal { x:Int, y:Int }",
-          "desc" : "Just like the arrows signal, but this uses keys w, a, s, and d,\nwhich are common controls for many computer games.\n"
-        },
-        { "name" : "directions",
-          "type" : "KeyCode -> KeyCode -> KeyCode -> KeyCode -> Signal { x:Int, y:Int }",
-          "desc" : "Custom key directions so that you can support different locales.\nThe plan is to have a locale independent version of this function\nthat uses the physical location of keys, but I don't know how to do it.\n"
-        },
-        { "name" : "isDown",
-          "type" : "KeyCode -> Signal Bool",
-          "desc" : "Whether an arbitrary key is pressed.\n"
-        },
-        { "name" : "shift",
-          "type" : "Signal Bool",
-          "desc" : "Whether the shift key is pressed.\n"
-        },
-        { "name" : "ctrl",
-          "type" : "Signal Bool",
-          "desc" : "Whether the control key is pressed.\n"
-        },
-        { "name" : "space",
-          "type" : "Signal Bool",
-          "desc" : "Whether the space key is pressed.\n"
-        },
-        { "name" : "enter",
-          "type" : "Signal Bool",
-          "desc" : "Whether the enter key is pressed.\n"
-        },
-        { "name" : "keysDown",
-          "type" : "Signal [KeyCode]",
-          "desc" : "List of keys that are currently down.\n"
-        },
-        { "name" : "lastPressed",
-          "type" : "Signal KeyCode",
-          "desc" : "The latest key that has been pressed.\n"
-        }
-      ]
-    },
-    { "name" : "Json",
-      "values" : [
-        { "name" : "String",
-          "type" : "String -> JsonValue",
-          "desc" : ""
-        },
-        { "name" : "Number",
-          "type" : "Float -> JsonValue",
-          "desc" : ""
-        },
-        { "name" : "Boolean",
-          "type" : "Bool -> JsonValue",
-          "desc" : ""
-        },
-        { "name" : "Null",
-          "type" : "JsonValue",
-          "desc" : ""
-        },
-        { "name" : "Array",
-          "type" : "[JsonValue] -> JsonValue",
-          "desc" : ""
-        },
-        { "name" : "Object",
-          "type" : "Dict String JsonValue -> JsonValue",
-          "desc" : ""
-        },
-        { "name" : "JsonValue",
-          "type" : "data JsonValue\n    = String String\n    | Number Float\n    | Boolean Bool\n    | Null\n    | Array [JsonValue]\n    | Object (Dict String JsonValue)",
-          "desc" : "This datatype can represent all valid values that can be held in a JSON\nobject. In Elm, a proper JSON object is represented as a (Dict String JsonValue)\nwhich is a mapping from strings to Json Values.\n"
-        },
-        { "name" : "toString",
-          "type" : "String -> JsonValue -> String",
-          "desc" : "Convert a `JsonValue` into a prettified string.\nThe first argument is a separator token (e.g. \\\" \\\", \\\"\\\\n\\\", etc.) that will\nbe used for indentation in the prettified string version of the JSON.\n"
-        },
-        { "name" : "toJSString",
-          "type" : "String -> JsonValue -> JSString",
-          "desc" : "Convert a proper JSON object into a JavaScript string.\nNote that the type JSString seen here is not the same as the type constructor\nJsonString used elsewhere in this module.\n"
-        },
-        { "name" : "fromString",
-          "type" : "String -> Maybe JsonValue",
-          "desc" : "Parse a string representation of a proper JSON object into\nits Elm representation.\n"
-        },
-        { "name" : "fromJSString",
-          "type" : "JSString -> Maybe JsonValue",
-          "desc" : "Parse a JavaScript string representation of a proper JSON object into\nits Elm representation.\n"
-        },
-        { "name" : "fromJSObject",
-          "type" : "JSObject -> JsonValue",
-          "desc" : "Convert a JS object into a `JsonValue`.\n"
-        },
-        { "name" : "toJSObject",
-          "type" : "JsonValue -> JSObject",
-          "desc" : "Convert a `JsonValue` into a `JSObject`. Paired with the\n[`JavaScript.Experimental` library](/docs/JavaScript/Experimental.elm),\nThis lets you convert strings into Elm records:\n\n      import JavaScript.Experimental as JS\n\n      stringToRecord str =\n          case fromString str of\n            Just jsonValue -> Just (JS.toRecord (toJSObject jsonValue))\n            Nothing -> Nothing\n"
-        }
-      ]
-    },
-    { "name" : "JavaScript",
-      "values" : [
-        { "name" : "toList",
-          "type" : "JSArray a -> [a]",
-          "desc" : "Requires that the input array be uniform (all members have the same type)\n"
-        },
-        { "name" : "toInt",
-          "type" : "JSNumber -> Int",
-          "desc" : ""
-        },
-        { "name" : "toFloat",
-          "type" : "JSNumber -> Float",
-          "desc" : ""
-        },
-        { "name" : "toBool",
-          "type" : "JSBool -> Bool",
-          "desc" : ""
-        },
-        { "name" : "toString",
-          "type" : "JSString -> String",
-          "desc" : ""
-        },
-        { "name" : "fromList",
-          "type" : "[a] -> JSArray a",
-          "desc" : "Produces a uniform JavaScript array with all members of the same type.\n"
-        },
-        { "name" : "fromInt",
-          "type" : "Int -> JSNumber",
-          "desc" : ""
-        },
-        { "name" : "fromFloat",
-          "type" : "Float -> JSNumber",
-          "desc" : ""
-        },
-        { "name" : "fromBool",
-          "type" : "Bool -> JSBool",
-          "desc" : ""
-        },
-        { "name" : "fromString",
-          "type" : "String -> JSString",
-          "desc" : ""
-        },
-        { "name" : "fromElement",
-          "type" : "Element -> JSDomNode",
-          "desc" : "Turn an `Element` into a plain old DOM node.\n"
-        },
-        { "name" : "toElement",
-          "type" : "Int -> Int -> JSDomNode -> Element",
-          "desc" : "Turn a DOM node into an `Element`. You can resize the node\nusing the normal `width` and `height` functions.\n"
-        }
-      ]
-    },
-    { "name" : "Http",
-      "values" : [
-        { "name" : "Success",
-          "type" : "t1 -> Response t1",
-          "desc" : ""
-        },
-        { "name" : "Waiting",
-          "type" : "Response t1",
-          "desc" : ""
-        },
-        { "name" : "Failure",
-          "type" : "Int -> String -> Response t1",
-          "desc" : ""
-        },
-        { "name" : "Response",
-          "type" : "data Response a = Success a | Waiting | Failure Int String",
-          "desc" : "The datatype for responses. Success contains only the returned message.\nFailures contain both an error code and an error message.\n"
-        },
-        { "name" : "Request",
-          "type" : "type Request a = {\n  verb : String,\n  url  : String,\n  body : a,\n  headers : [(String,String)]\n }",
-          "desc" : ""
-        },
-        { "name" : "request",
-          "type" : "String -> String -> String -> [(String,String)] -> Request String",
-          "desc" : "Create a customized request. Arguments are request type (get, post, put,\ndelete, etc.), target url, data, and a list of additional headers.\n"
-        },
-        { "name" : "get",
-          "type" : "String -> Request String",
-          "desc" : "Create a GET request to the given url.\n"
-        },
-        { "name" : "post",
-          "type" : "String -> String -> Request String",
-          "desc" : "Create a POST request to the given url, carrying the given data.\n"
-        },
-        { "name" : "send",
-          "type" : "Signal (Request a) -> Signal (Response String)",
-          "desc" : "Performs an HTTP request with the given requests. Produces a signal\nthat carries the responses.\n"
-        },
-        { "name" : "sendGet",
-          "type" : "Signal String -> Signal (Response String)",
-          "desc" : "Performs an HTTP GET request with the given urls. Produces a signal\nthat carries the responses.\n"
-        }
-      ]
-    },
-    { "name" : "Either",
-      "values" : [
-        { "name" : "Left",
-          "type" : "t1 -> Either t1 t2",
-          "desc" : ""
-        },
-        { "name" : "Right",
-          "type" : "t2 -> Either t1 t2",
-          "desc" : ""
-        },
-        { "name" : "Either",
-          "type" : "data Either a b = Left a | Right b",
-          "desc" : "Represents any data that can take two different types.\n\nThis can also be used for error handling `(Either String a)` where error\nmessages are stored on the left, and the correct values (&ldquo;right&rdquo;\nvalues) are stored on the right.\n"
-        },
-        { "name" : "either",
-          "type" : "(a -> c) -> (b -> c) -> Either a b -> c",
-          "desc" : "Apply the first function to a `Left` and the second function to a `Right`.\nThis allows the extraction of a value from an `Either`.\n"
-        },
-        { "name" : "isLeft",
-          "type" : "Either a b -> Bool",
-          "desc" : "True if the value is a `Left`.\n"
-        },
-        { "name" : "isRight",
-          "type" : "Either a b -> Bool",
-          "desc" : "True if the value is a `Right`.\n"
-        },
-        { "name" : "lefts",
-          "type" : "[Either a b] -> [a]",
-          "desc" : "Keep only the values held in `Left` values.\n"
-        },
-        { "name" : "rights",
-          "type" : "[Either a b] -> [b]",
-          "desc" : "Keep only the values held in `Right` values.\n"
-        },
-        { "name" : "partition",
-          "type" : "[Either a b] -> ([a],[b])",
-          "desc" : "Split into two lists, lefts on the left and rights on the right. So we\nhave the equivalence: `(partition es == (lefts es, rights es))`\n"
-        }
-      ]
-    },
-    { "name" : "Dict",
-      "values" : [
-        { "name" : "Red",
-          "type" : "NColor",
-          "desc" : ""
-        },
-        { "name" : "Black",
-          "type" : "NColor",
-          "desc" : ""
-        },
-        { "name" : "RBNode",
-          "type" : "NColor -> t1 -> t2 -> Dict t1 t2 -> Dict t1 t2 -> Dict t1 t2",
-          "desc" : ""
-        },
-        { "name" : "RBEmpty",
-          "type" : "Dict t1 t2",
-          "desc" : ""
-        },
-        { "name" : "empty",
-          "type" : "Dict (Comparable k) v",
-          "desc" : "Create an empty dictionary.\n"
-        },
-        { "name" : "lookup",
-          "type" : "Comparable k -> Dict (Comparable k) v -> Maybe v",
-          "desc" : "Lookup the value associated with a key.\n"
-        },
-        { "name" : "findWithDefault",
-          "type" : "v -> Comparable k -> Dict (Comparable k) v -> v",
-          "desc" : "Find the value associated with a key. If the key is not found,\nreturn the default value.\n"
-        },
-        { "name" : "member",
-          "type" : "Comparable k -> Dict (Comparable k) v -> Bool",
-          "desc" : "Determine if a key is in a dictionary.\n"
-        },
-        { "name" : "insert",
-          "type" : "Comparable k -> v -> Dict (Comparable k) v -> Dict (Comparable k) v",
-          "desc" : "Insert a key-value pair into a dictionary. Replaces value when there is\na collision.\n"
-        },
-        { "name" : "singleton",
-          "type" : "Comparable k -> v -> Dict (Comparable k) v",
-          "desc" : "Create a dictionary with one key-value pair.\n"
-        },
-        { "name" : "remove",
-          "type" : "Comparable k -> Dict (Comparable k) v -> Dict (Comparable k) v",
-          "desc" : "Remove a key-value pair from a dictionary. If the key is not found,\nno changes are made.\n"
-        },
-        { "name" : "map",
-          "type" : "(a -> b) -> Dict (Comparable k) a -> Dict (Comparable k) b",
-          "desc" : "Apply a function to all values in a dictionary.\n"
-        },
-        { "name" : "foldl",
-          "type" : "(Comparable k -> v -> b -> b) -> b -> Dict (Comparable k) v -> b",
-          "desc" : "Fold over the key-value pairs in a dictionary, in order from lowest\nkey to highest key.\n"
-        },
-        { "name" : "foldr",
-          "type" : "(Comparable k -> v -> b -> b) -> b -> Dict (Comparable k) v -> b",
-          "desc" : "Fold over the key-value pairs in a dictionary, in order from highest\nkey to lowest key.\n"
-        },
-        { "name" : "union",
-          "type" : "Dict (Comparable k) v -> Dict (Comparable k) v -> Dict (Comparable k) v",
-          "desc" : "Combine two dictionaries. If there is a collision, preference is given\nto the first dictionary.\n"
-        },
-        { "name" : "intersect",
-          "type" : "Dict (Comparable k) v -> Dict (Comparable k) v -> Dict (Comparable k) v",
-          "desc" : "Keep a key-value pair when its key appears in the second dictionary.\nPreference is given to values in the first dictionary.\n"
-        },
-        { "name" : "diff",
-          "type" : "Dict (Comparable k) v -> Dict (Comparable k) v -> Dict (Comparable k) v",
-          "desc" : "Keep a key-value pair when its key does not appear in the second dictionary.\nPreference is given to the first dictionary.\n"
-        },
-        { "name" : "keys",
-          "type" : "Dict (Comparable k) v -> [Comparable k]",
-          "desc" : "Get all of the keys in a dictionary.\n"
-        },
-        { "name" : "values",
-          "type" : "Dict (Comparable k) v -> [v]",
-          "desc" : "Get all of the values in a dictionary.\n"
-        },
-        { "name" : "toList",
-          "type" : "Dict (Comparable k) v -> [(Comparable k,v)]",
-          "desc" : "Convert a dictionary into an association list of key-value pairs.\n"
-        },
-        { "name" : "fromList",
-          "type" : "[(Comparable k,v)] -> Dict (Comparable k) v",
-          "desc" : "Convert an association list into a dictionary.\n"
-        }
-      ]
-    },
-    { "name" : "Date",
-      "values" : [
-        { "name" : "Mon",
-          "type" : "Day",
-          "desc" : ""
-        },
-        { "name" : "Tue",
-          "type" : "Day",
-          "desc" : ""
-        },
-        { "name" : "Wed",
-          "type" : "Day",
-          "desc" : ""
-        },
-        { "name" : "Thu",
-          "type" : "Day",
-          "desc" : ""
-        },
-        { "name" : "Fri",
-          "type" : "Day",
-          "desc" : ""
-        },
-        { "name" : "Sat",
-          "type" : "Day",
-          "desc" : ""
-        },
-        { "name" : "Sun",
-          "type" : "Day",
-          "desc" : ""
-        },
-        { "name" : "Day",
-          "type" : "data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun",
-          "desc" : "Represents the days of the week.\n"
-        },
-        { "name" : "Jan",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Feb",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Mar",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Apr",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "May",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Jun",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Jul",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Aug",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Sep",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Oct",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Nov",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Dec",
-          "type" : "Month",
-          "desc" : ""
-        },
-        { "name" : "Month",
-          "type" : "data Month = Jan | Feb | Mar | Apr\n           | May | Jun | Jul | Aug\n           | Sep | Oct | Nov | Dec",
-          "desc" : "Represents the month of the year.\n"
-        },
-        { "name" : "read",
-          "type" : "String -> Maybe Date",
-          "desc" : "Attempt to read a date from a string.\n"
-        },
-        { "name" : "toTime",
-          "type" : "Date -> Time",
-          "desc" : "Convert a date into a time since midnight (UTC) of 1 January 1990 (i.e.\n[UNIX time](http://en.wikipedia.org/wiki/Unix_time)). Given the date 23 June\n1990 at 11:45AM this returns the corresponding time.\n"
-        },
-        { "name" : "year",
-          "type" : "Date -> Int",
-          "desc" : "Extract the year of a given date. Given the date 23 June 1990 at 11:45AM\nthis returns the integer `1990`.\n"
-        },
-        { "name" : "month",
-          "type" : "Date -> Month",
-          "desc" : "Extract the month of a given date. Given the date 23 June 1990 at 11:45AM\nthis returns the Month `Jun` as defined below.\n"
-        },
-        { "name" : "day",
-          "type" : "Date -> Int",
-          "desc" : "Extract the day of a given date. Given the date 23 June 1990 at 11:45AM\nthis returns the integer `23`.\n"
-        },
-        { "name" : "dayOfWeek",
-          "type" : "Date -> Day",
-          "desc" : "Extract the day of the week for a given date. Given the date 23 June\n1990 at 11:45AM this returns the Day `Thu` as defined below.\n"
-        },
-        { "name" : "hour",
-          "type" : "Date -> Int",
-          "desc" : "Extract the hour of a given date. Given the date 23 June 1990 at 11:45AM\nthis returns the integer `11`.\n"
-        },
-        { "name" : "minute",
-          "type" : "Date -> Int",
-          "desc" : "Extract the minute of a given date. Given the date 23 June 1990 at 11:45AM\nthis returns the integer `45`.\n"
-        },
-        { "name" : "second",
-          "type" : "Date -> Int",
-          "desc" : "Extract the second of a given date. Given the date 23 June 1990 at 11:45AM\nthis returns the integer `0`.\n"
-        }
-      ]
-    },
-    { "name" : "Color",
-      "values" : [
-        { "name" : "Color",
-          "type" : "Int -> Int -> Int -> Float -> Color",
-          "desc" : ""
-        },
-        { "name" : "Color",
-          "type" : "data Color = Color Int Int Int Float",
-          "desc" : ""
-        },
-        { "name" : "rgba",
-          "type" : "Int -> Int -> Int -> Float -> Color",
-          "desc" : "Create RGB colors with an alpha component for transparency.\nThe alpha component is specified with numbers between 0 and 1.\n"
-        },
-        { "name" : "rgb",
-          "type" : "Int -> Int -> Int -> Color",
-          "desc" : "Create RGB colors from numbers between 0 and 255 inclusive.\n"
-        },
-        { "name" : "red",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "lime",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "blue",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "yellow",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "cyan",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "magenta",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "black",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "white",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "gray",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "grey",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "maroon",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "navy",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "green",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "teal",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "purple",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "violet",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "forestGreen",
-          "type" : "Color",
-          "desc" : ""
-        },
-        { "name" : "complement",
-          "type" : "Color -> Color",
-          "desc" : "Produce a &ldquo;complementary color&rdquo;.\nThe two colors will accent each other.\n"
-        },
-        { "name" : "hsva",
-          "type" : "Float -> Float -> Float -> Float -> Color",
-          "desc" : "Create [HSV colors](http://en.wikipedia.org/wiki/HSL_and_HSV)\nwith an alpha component for transparency.\n"
-        },
-        { "name" : "hsv",
-          "type" : "Float -> Float -> Float -> Color",
-          "desc" : "Create [HSV colors](http://en.wikipedia.org/wiki/HSL_and_HSV).\nThis is very convenient for creating colors that cycle and shift.\n\n        hsv (degrees 240) 1 1 == blue\n"
-        },
-        { "name" : "Linear",
-          "type" : "(Float,Float) -> (Float,Float) -> [(Float,Color)] -> Gradient",
-          "desc" : ""
-        },
-        { "name" : "Radial",
-          "type" : "(Float,Float) -> Float -> (Float,Float) -> Float -> [(Float,Color)] -> Gradient",
-          "desc" : ""
-        },
-        { "name" : "Gradient",
-          "type" : "data Gradient\n  = Linear (Float,Float) (Float,Float) [(Float,Color)]\n  | Radial (Float,Float) Float (Float,Float) Float [(Float,Color)]",
-          "desc" : ""
-        },
-        { "name" : "linear",
-          "type" : "(Number a, Number a) -> (Number a, Number a) -> [(Float,Color)] -> Gradient",
-          "desc" : "Create a linear gradient. Takes a start and end point and then a series\nof &ldquo;color stops&rdquo; that indicate how to interpolate between\nthe start and end points. See [this example](/edit/examples/Elements/LinearGradient.elm) for\na more visual explanation.\n"
-        },
-        { "name" : "radial",
-          "type" : "(Number a,Number a) -> Number a -> (Number a,Number a) -> Number a -> [(Float,Color)] -> Gradient",
-          "desc" : "Create a radial gradient. First takes a start point and inner radius.\nThen takes an end point and outer radius. It then takes a series\nof &ldquo;color stops&rdquo; that indicate how to interpolate between\nthe inner and outer circles. See [this example](/edit/examples/Elements/RadialGradient.elm) for\na more visual explanation.\n"
-        }
-      ]
-    },
-    { "name" : "Char",
-      "values" : [
-        { "name" : "isUpper",
-          "type" : "Char -> Bool",
-          "desc" : "True for upper case letters.\n"
-        },
-        { "name" : "isLower",
-          "type" : "Char -> Bool",
-          "desc" : "True for lower case letters.\n"
-        },
-        { "name" : "isDigit",
-          "type" : "Char -> Bool",
-          "desc" : "True for ASCII digits (`0..9`).\n"
-        },
-        { "name" : "isOctDigit",
-          "type" : "Char -> Bool",
-          "desc" : "True for ASCII octal digits (`0..7`).\n"
-        },
-        { "name" : "isHexDigit",
-          "type" : "Char -> Bool",
-          "desc" : "True for ASCII hexadecimal digits (`0..9a..fA..F`).\n"
-        },
-        { "name" : "toUpper",
-          "type" : "Char -> Char",
-          "desc" : "Convert to upper case.\n"
-        },
-        { "name" : "toLower",
-          "type" : "Char -> Char",
-          "desc" : "Convert to lower case.\n"
-        },
-        { "name" : "toLocaleUpper",
-          "type" : "Char -> Char",
-          "desc" : "Convert to upper case, according to any locale-specific case mappings.\n"
-        },
-        { "name" : "toLocaleLower",
-          "type" : "Char -> Char",
-          "desc" : "Convert to lower case, according to any locale-specific case mappings.\n"
-        },
-        { "name" : "toCode",
-          "type" : "Char -> KeyCode",
-          "desc" : "Convert to unicode.\n"
-        },
-        { "name" : "fromCode",
-          "type" : "KeyCode -> Char",
-          "desc" : "Convert from unicode.\n"
-        }
-      ]
-    },
-    { "name" : "Automaton",
-      "values" : [
-        { "name" : "Step",
-          "type" : "(t1 -> (Automaton t1 t2,t2)) -> Automaton t1 t2",
-          "desc" : ""
-        },
-        { "name" : "Automaton",
-          "type" : "data Automaton a b = Step (a -> (Automaton a b, b))",
-          "desc" : ""
-        },
-        { "name" : "run",
-          "type" : "Automaton a b -> b -> Signal a -> Signal b",
-          "desc" : "Run an automaton on a given signal. The automaton steps forward\nwhenever the input signal updates.\n"
-        },
-        { "name" : "step",
-          "type" : "a -> Automaton a b -> (Automaton a b, b)",
-          "desc" : "Step an automaton forward once with a given input.\n"
-        },
-        { "name" : ">>>",
-          "type" : "Automaton a b -> Automaton b c -> Automaton a c",
-          "desc" : "Compose two automatons, chaining them together.\n"
-        },
-        { "name" : "<<<",
-          "type" : "Automaton b c -> Automaton a b -> Automaton a c",
-          "desc" : "Compose two automatons, chaining them together.\n"
-        },
-        { "name" : "combine",
-          "type" : "[Automaton a b] -> Automaton a [b]",
-          "desc" : "Combine a list of automatons into a single automaton that produces a list.\n"
-        },
-        { "name" : "pure",
-          "type" : "(a -> b) -> Automaton a b",
-          "desc" : "Create an automaton with no memory. It just applies the given function to\nevery input.\n"
-        },
-        { "name" : "state",
-          "type" : "b -> (a -> b -> b) -> Automaton a b",
-          "desc" : "Create an automaton with state. Requires an initial state and a step\nfunction to step the state forward. For example, an automaton that counted\nhow many steps it has taken would look like this:\n\n        count = Automaton a Int\n        count = state 0 (\\\\_ c -> c+1)\n\nIt is a stateful automaton. The initial state is zero, and the step function\nincrements the state on every step.\n"
-        },
-        { "name" : "hiddenState",
-          "type" : "s -> (a -> s -> (s,b)) -> Automaton a b",
-          "desc" : "Create an automaton with hidden state. Requires an initial state and a\nstep function to step the state forward and produce an output.\n"
-        },
-        { "name" : "count",
-          "type" : "Automaton a Int",
-          "desc" : "Count the number of steps taken.\n"
-        },
-        { "name" : "Queue",
-          "type" : "type Queue t = ([t],[t])",
-          "desc" : ""
-        },
-        { "name" : "average",
-          "type" : "Int -> Automaton Float Float",
-          "desc" : "Computes the running average of the last `n` inputs.\n"
-        }
-      ]
-    },
-    { "name" : "JavaScript.Experimental",
-      "values" : [
-        { "name" : "toRecord",
-          "type" : "JSObject -> a",
-          "desc" : "Turn arbitrary JavaScript objects into Elm records.\nArrays are converted into lists, nested objects are allowed.\nNo `null` values or non-homogeneous arrays.\n\n        -- OK objects\n        { student:\"Steve\", scores:[83,94,99,72] }\n        { errorLevel:10, critical:true }\n\n        -- BAD objects\n        { answer:null }\n        { info:[true,42,'what'] }\n"
-        },
-        { "name" : "fromRecord",
-          "type" : "a -> JSObject",
-          "desc" : "Turn arbitrary Elm records into JavaScript objects.\nLists become arrays, nested records are allowed. No ADTs.\n\n        -- OK records\n        { student=\"Steve\", scores=[83,94,99,72] }\n        { errorLevel=10, critical=True }\n\n        -- BAD records\n        { answer = Nothing }\n        { result = Left \"An error occurred\" }\n"
-        }
-      ]
-    },
-    { "name" : "Graphics.Input",
-      "values" : [
-        { "name" : "buttons",
-          "type" : "a -> { events : Signal a,\n                 button : a -> String -> Element }",
-          "desc" : "Create a group of buttons.\n\n* The first argument is the default value of the `events` signal.\n* The `events` signal represents all of the activity in this group\n  of buttons.\n* The `button` function creates a button\n  with the given name, like &ldquo;Submit&rdquo; or &ldquo;Cancel&rdquo;.\n  The `a` value is sent to `events` whenever the button is pressed.\n"
-        },
-        { "name" : "button",
-          "type" : "String -> (Element, Signal ())",
-          "desc" : "Create a button with a given label. The result is an `Element` and\na signal of units. This signal triggers whenever the button is pressed.\n"
-        },
-        { "name" : "customButtons",
-          "type" : "a -> { events : Signal a,\n                       customButton : a -> Element -> Element -> Element -> Element }",
-          "desc" : "Create a group of custom buttons.\n\n* The first argument is the default value of the `events` signal.\n* The `events` signal represents all of the activity in this group\n  of custom buttons.\n* The `customButton` function creates a button with three different visual\n  states, one for up, hovering, and down. The resulting button has dimensions\n  large enough to fit all three possible `Elements`.\n  The `a` value is sent to `events` whenever the button is pressed.\n"
-        },
-        { "name" : "customButton",
-          "type" : "Element -> Element -> Element -> (Element, Signal ())",
-          "desc" : "Create a button with custom states for up, hovering, and down\n(given in that order). The result is an `Element` and\na signal of units. This signal triggers whenever the button is pressed.\n"
-        },
-        { "name" : "checkboxes",
-          "type" : "a -> { events : Signal a,\n                    checkbox : (Bool -> a) -> Bool -> Element }",
-          "desc" : "Create a group of checkboxes.\n\n* The first argument is the default value of the `events` signal.\n* The `events` signal represents all of the activity in this group\n  of checkboxes.\n* The `checkbox` function creates a\n  checkbox with a given state. The `(Bool -> a)` function is used\n  when the checkbox is modified. It takes the new state and turns\n  it into a value that can be sent to `events`. For example, this\n  lets you add an ID to distinguish between checkboxes.\n"
-        },
-        { "name" : "checkbox",
-          "type" : "Bool -> (Signal Element, Signal Bool)",
-          "desc" : "Create a checkbox with a given start state. Unlike `button`, this result\nis a *signal* of elements. That is because a checkbox has state that\nupdates based on user input.\nThe boolean signal represents the current state of the checkbox.\n"
-        },
-        { "name" : "FieldState",
-          "type" : "type FieldState = { string:String, selectionStart:Int, selectionEnd:Int }",
-          "desc" : "Represents the current state of a text field. The `string` represents the\ncharacters filling the text field. The `selectionStart` and `selectionEnd`\nvalues represent what the user has selected with their mouse or keyboard.\nFor example:\n\n        { string=\"She sells sea shells\", selectionStart=3, selectionEnd=0 }\n\nThis means the user highlighted the substring `\"She\"` backwards.\n"
-        },
-        { "name" : "fields",
-          "type" : "a -> { events : Signal a,\n                field : (FieldState -> a) -> String -> FieldState -> Element }",
-          "desc" : "Create a group of text input fields.\n\n* The first argument is the default value of the `events` signal.\n* The `events` signal represents all of the activity in this group\n  of text fields.\n* The `field` function creates a\n  field with the given ghost text and initial field state.\n  When the field is modified, the `(FieldState -> a)` function\n  takes the new state and turns\n  it into a value that can be sent to `events`. For example, this\n  lets you add an ID to distinguish between input fields.\n"
-        },
-        { "name" : "emptyFieldState",
-          "type" : "FieldState",
-          "desc" : "The empty field state:\n\n        { string=\"\", selectionStart=0, selectionEnd=0 }\n"
-        },
-        { "name" : "field",
-          "type" : "String -> (Signal Element, Signal String)",
-          "desc" : "Create a field with the given default text. The output is an element that\nupdates to match the user input and a signal of strings representing the\ncontent of the field.\n"
-        },
-        { "name" : "password",
-          "type" : "String -> (Signal Element, Signal String)",
-          "desc" : "Same as `field` but the UI element blocks out each characters.\n"
-        },
-        { "name" : "email",
-          "type" : "String -> (Signal Element, Signal String)",
-          "desc" : "Same as `field` but it adds an annotation that this field is for email\naddresses. This is helpful for auto-complete and for mobile users who may\nget a custom keyboard with an `@` and `.com` button.\n"
-        },
-        { "name" : "dropDown",
-          "type" : "[(String,a)] -> (Signal Element, Signal a)",
-          "desc" : "Create a drop-down menu. When the user selects a string,\nthe current state of the drop-down is set to the associated\nvalue. This lets you avoid manually mapping the string onto\nfunctions and values.\n"
-        },
-        { "name" : "stringDropDown",
-          "type" : "[String] -> (Signal Element, Signal String)",
-          "desc" : "Create a drop-down menu for selecting strings. The resulting\nsignal of strings represents the string that is currently selected.\n"
-        }
-      ]
-    },
-    { "name" : "Graphics.Element",
-      "values" : [
-        { "name" : "widthOf",
-          "type" : "Element -> Int",
-          "desc" : "Get the width of an Element\n"
-        },
-        { "name" : "heightOf",
-          "type" : "Element -> Int",
-          "desc" : "Get the height of an Element\n"
-        },
-        { "name" : "sizeOf",
-          "type" : "Element -> (Int,Int)",
-          "desc" : "Get the width and height of an Element\n"
-        },
-        { "name" : "width",
-          "type" : "Int -> Element -> Element",
-          "desc" : "Create an `Element` with a given width.\n"
-        },
-        { "name" : "height",
-          "type" : "Int -> Element -> Element",
-          "desc" : "Create an `Element` with a given height.\n"
-        },
-        { "name" : "size",
-          "type" : "Int -> Int -> Element -> Element",
-          "desc" : "Create an `Element` with a new width and height.\n"
-        },
-        { "name" : "opacity",
-          "type" : "Float -> Element -> Element",
-          "desc" : "Create an `Element` with a given opacity. Opacity is a number between 0 and 1\nwhere 0 means totally clear.\n"
-        },
-        { "name" : "color",
-          "type" : "Color -> Element -> Element",
-          "desc" : "Create an `Element` with a given background color.\n"
-        },
-        { "name" : "tag",
-          "type" : "String -> Element -> Element",
-          "desc" : "Create an `Element` with a tag. This lets you link directly to it.\nThe element `(tag \"all-about-badgers\" thirdParagraph)` can be reached\nwith a link lik this: `/facts-about-animals.elm#all-about-badgers`\n"
-        },
-        { "name" : "link",
-          "type" : "String -> Element -> Element",
-          "desc" : "Create an `Element` that is a hyper-link.\n"
-        },
-        { "name" : "Image",
-          "type" : "ImageStyle -> Int -> Int -> JSString -> ElementPrim",
-          "desc" : ""
-        },
-        { "name" : "Container",
-          "type" : "Position -> Element -> ElementPrim",
-          "desc" : ""
-        },
-        { "name" : "Flow",
-          "type" : "Direction -> [Element] -> ElementPrim",
-          "desc" : ""
-        },
-        { "name" : "Spacer",
-          "type" : "ElementPrim",
-          "desc" : ""
-        },
-        { "name" : "RawHtml",
-          "type" : "JSString -> ElementPrim",
-          "desc" : ""
-        },
-        { "name" : "Custom",
-          "type" : "ElementPrim",
-          "desc" : ""
-        },
-        { "name" : "Plain",
-          "type" : "ImageStyle",
-          "desc" : ""
-        },
-        { "name" : "Fitted",
-          "type" : "ImageStyle",
-          "desc" : ""
-        },
-        { "name" : "Cropped",
-          "type" : "(Int,Int) -> ImageStyle",
-          "desc" : ""
-        },
-        { "name" : "Tiled",
-          "type" : "ImageStyle",
-          "desc" : ""
-        },
-        { "name" : "image",
-          "type" : "Int -> Int -> String -> Element",
-          "desc" : "Create an image given a width, height, and image source.\n"
-        },
-        { "name" : "fittedImage",
-          "type" : "Int -> Int -> String -> Element",
-          "desc" : "Create a fitted image given a width, height, and image source.\nThis will crop the picture to best fill the given dimensions.\n"
-        },
-        { "name" : "croppedImage",
-          "type" : "(Int,Int) -> Int -> Int -> String -> Element",
-          "desc" : "Create a cropped image. Take a rectangle out of the picture starting\nat the given top left coordinate. If you have a 140-by-140 image,\nthe following will cut a 100-by-100 square out of the middle of it.\n\n        croppedImage (20,20) 100 100 \"yogi.jpg\"\n"
-        },
-        { "name" : "tiledImage",
-          "type" : "Int -> Int -> String -> Element",
-          "desc" : ""
-        },
-        { "name" : "P",
-          "type" : "Three",
-          "desc" : ""
-        },
-        { "name" : "Z",
-          "type" : "Three",
-          "desc" : ""
-        },
-        { "name" : "N",
-          "type" : "Three",
-          "desc" : ""
-        },
-        { "name" : "Absolute",
-          "type" : "Int -> Pos",
-          "desc" : ""
-        },
-        { "name" : "Relative",
-          "type" : "Float -> Pos",
-          "desc" : ""
-        },
-        { "name" : "container",
-          "type" : "Int -> Int -> Position -> Element -> Element",
-          "desc" : "Put an element in a container. This lets you position the element really\neasily, and there are tons of ways to set the `Position`.\nTo center `element` exactly in a 300-by-300 square you would say:\n\n        container 300 300 middle element\n\nBy setting the color of the container, you can create borders.\n"
-        },
-        { "name" : "spacer",
-          "type" : "Int -> Int -> Element",
-          "desc" : "Create an empty box. This is useful for getting your spacing right and\nfor making borders.\n"
-        },
-        { "name" : "DUp",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "DDown",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "DLeft",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "DRight",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "DIn",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "DOut",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "flow",
-          "type" : "Direction -> [Element] -> Element",
-          "desc" : "Have a list of elements flow in a particular direction.\nThe `Direction` starts from the first element in the list.\n\n        flow right [a,b,c]\n\n          +---+---+---+\n          | a | b | c |\n          +---+---+---+\n"
-        },
-        { "name" : "above",
-          "type" : "Element -> Element -> Element",
-          "desc" : "Stack elements vertically. To put `a` above `b` you would say:\n\n        a `above` b\n"
-        },
-        { "name" : "below",
-          "type" : "Element -> Element -> Element",
-          "desc" : "Stack elements vertically. To put `a` below `b` you would say:\n\n        a `below` b\n"
-        },
-        { "name" : "beside",
-          "type" : "Element -> Element -> Element",
-          "desc" : "Put elements beside each other horizontally.\n"
-        },
-        { "name" : "layers",
-          "type" : "[Element] -> Element",
-          "desc" : "Layer elements on top of each other, starting from the bottom.\n`(layers == flow outward)`\n"
-        },
-        { "name" : "absolute",
-          "type" : "Int -> Pos",
-          "desc" : ""
-        },
-        { "name" : "relative",
-          "type" : "Float -> Pos",
-          "desc" : ""
-        },
-        { "name" : "middle",
-          "type" : "Position",
-          "desc" : ""
-        },
-        { "name" : "topLeft",
-          "type" : "Position",
-          "desc" : ""
-        },
-        { "name" : "topRight",
-          "type" : "Position",
-          "desc" : ""
-        },
-        { "name" : "bottomLeft",
-          "type" : "Position",
-          "desc" : ""
-        },
-        { "name" : "bottomRight",
-          "type" : "Position",
-          "desc" : ""
-        },
-        { "name" : "midLeft",
-          "type" : "Position",
-          "desc" : ""
-        },
-        { "name" : "midRight",
-          "type" : "Position",
-          "desc" : ""
-        },
-        { "name" : "midTop",
-          "type" : "Position",
-          "desc" : ""
-        },
-        { "name" : "midBottom",
-          "type" : "Position",
-          "desc" : ""
-        },
-        { "name" : "middleAt",
-          "type" : "Pos -> Pos -> Position",
-          "desc" : ""
-        },
-        { "name" : "topLeftAt",
-          "type" : "Pos -> Pos -> Position",
-          "desc" : ""
-        },
-        { "name" : "topRightAt",
-          "type" : "Pos -> Pos -> Position",
-          "desc" : ""
-        },
-        { "name" : "bottomLeftAt",
-          "type" : "Pos -> Pos -> Position",
-          "desc" : ""
-        },
-        { "name" : "bottomRightAt",
-          "type" : "Pos -> Pos -> Position",
-          "desc" : ""
-        },
-        { "name" : "midLeftAt",
-          "type" : "Pos -> Pos -> Position",
-          "desc" : ""
-        },
-        { "name" : "midRightAt",
-          "type" : "Pos -> Pos -> Position",
-          "desc" : ""
-        },
-        { "name" : "midTopAt",
-          "type" : "Pos -> Pos -> Position",
-          "desc" : ""
-        },
-        { "name" : "midBottomAt",
-          "type" : "Pos -> Pos -> Position",
-          "desc" : ""
-        },
-        { "name" : "up",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "down",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "left",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "right",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "inward",
-          "type" : "Direction",
-          "desc" : ""
-        },
-        { "name" : "outward",
-          "type" : "Direction",
-          "desc" : ""
-        }
-      ]
-    },
-    { "name" : "Graphics.Collage",
-      "values" : [
-        { "name" : "Form",
-          "type" : "type Form = {\n  theta : Float,\n  scale : Float,\n  x : Float,\n  y : Float,\n  form : BasicForm\n }",
-          "desc" : ""
-        },
-        { "name" : "Solid",
-          "type" : "Color -> FillStyle",
-          "desc" : ""
-        },
-        { "name" : "Texture",
-          "type" : "String -> FillStyle",
-          "desc" : ""
-        },
-        { "name" : "Gradient",
-          "type" : "Gradient -> FillStyle",
-          "desc" : ""
-        },
-        { "name" : "FillStyle",
-          "type" : "data FillStyle\n  = Solid Color\n  | Texture String\n  | Gradient Gradient",
-          "desc" : ""
-        },
-        { "name" : "Flat",
-          "type" : "LineCap",
-          "desc" : ""
-        },
-        { "name" : "Round",
-          "type" : "LineCap",
-          "desc" : ""
-        },
-        { "name" : "Padded",
-          "type" : "LineCap",
-          "desc" : ""
-        },
-        { "name" : "LineCap",
-          "type" : "data LineCap = Flat | Round | Padded",
-          "desc" : "The shape of the ends of a line. \n"
-        },
-        { "name" : "Smooth",
-          "type" : "LineJoin",
-          "desc" : ""
-        },
-        { "name" : "Sharp",
-          "type" : "Float -> LineJoin",
-          "desc" : ""
-        },
-        { "name" : "Clipped",
-          "type" : "LineJoin",
-          "desc" : ""
-        },
-        { "name" : "LineJoin",
-          "type" : "data LineJoin = Smooth | Sharp Float | Clipped",
-          "desc" : "The shape of the &ldquo;joints&rdquo; of a line, where each line segment\nmeets. `Sharp` takes an argument to limit the length of the joint. This\ndefaults to 10.\n"
-        },
-        { "name" : "LineStyle",
-          "type" : "type LineStyle = {\n  color : Color,\n  width : Float,\n  cap   : LineCap,\n  join  : LineJoin,\n  dashing    : [Int],\n  dashOffset : Int\n }",
-          "desc" : "All of the attributes of a line style. This lets you build up a line style\nhowever you want. You can also update existing line styles with record updates.\n"
-        },
-        { "name" : "defaultLine",
-          "type" : "LineStyle",
-          "desc" : "The default line style, which is solid black with flat caps and sharp joints.\nYou can use record updates to build the line style you\nwant. For example, to make a thicker line, you could say:\n\n        { defaultLine | width <- 10 }\n"
-        },
-        { "name" : "solid",
-          "type" : "Color -> LineStyle",
-          "desc" : "Create a solid line style with a given color.\n"
-        },
-        { "name" : "dashed",
-          "type" : "Color -> LineStyle",
-          "desc" : "Create a dashed line style with a given color. Dashing equals `[8,4]`.\n"
-        },
-        { "name" : "dotted",
-          "type" : "Color -> LineStyle",
-          "desc" : "Create a dotted line style with a given color. Dashing equals `[3,3]`.\n"
-        },
-        { "name" : "FPath",
-          "type" : "LineStyle -> Path -> BasicForm",
-          "desc" : ""
-        },
-        { "name" : "FShape",
-          "type" : "Either LineStyle FillStyle -> Shape -> BasicForm",
-          "desc" : ""
-        },
-        { "name" : "FImage",
-          "type" : "Int -> Int -> (Int,Int) -> String -> BasicForm",
-          "desc" : ""
-        },
-        { "name" : "FElement",
-          "type" : "Element -> BasicForm",
-          "desc" : ""
-        },
-        { "name" : "FGroup",
-          "type" : "Matrix2D -> [Form] -> BasicForm",
-          "desc" : ""
-        },
-        { "name" : "BasicForm",
-          "type" : "data BasicForm\n  = FPath LineStyle Path\n  | FShape (Either LineStyle FillStyle) Shape\n  | FImage Int Int (Int,Int) String\n  | FElement Element\n  | FGroup Matrix2D [Form]",
-          "desc" : ""
-        },
-        { "name" : "filled",
-          "type" : "Color -> Shape -> Form",
-          "desc" : "Create a filled in shape.\n"
-        },
-        { "name" : "textured",
-          "type" : "String -> Shape -> Form",
-          "desc" : "Create a textured shape. The texture is described by some url and is\ntiled to fill the entire shape.\n"
-        },
-        { "name" : "gradient",
-          "type" : "Gradient -> Shape -> Form",
-          "desc" : "Fill a shape with a [gradient](/docs/Color.elm#linear).\n"
-        },
-        { "name" : "outlined",
-          "type" : "LineStyle -> Shape -> Form",
-          "desc" : "Outline a shape with a given line style.\n"
-        },
-        { "name" : "traced",
-          "type" : "LineStyle -> Path -> Form",
-          "desc" : "Trace a path with a given line style.\n"
-        },
-        { "name" : "sprite",
-          "type" : "Int -> Int -> (Int,Int) -> String -> Form",
-          "desc" : "Create a sprite from a sprite sheet. It cuts out a rectangle\nat a given position.\n"
-        },
-        { "name" : "toForm",
-          "type" : "Element -> Form",
-          "desc" : "Turn any `Element` into a `Form`. This lets you use text, gifs, and video\nin your collage. This means you can move, rotate, and scale\nan `Element` however you want.\n"
-        },
-        { "name" : "group",
-          "type" : "[Form] -> Form",
-          "desc" : "Flatten many forms into a single `Form`. This lets you move and rotate them\nas a single unit, making it possible to build small, modular components.\n"
-        },
-        { "name" : "groupTransform",
-          "type" : "Matrix2D -> [Form] -> Form",
-          "desc" : "Flatten many forms into a single `Form` and then apply a matrix\ntransformation.\n"
-        },
-        { "name" : "rotate",
-          "type" : "Float -> Form -> Form",
-          "desc" : "Rotate a form by a given angle. Rotate takes standard Elm angles (radians)\nand turns things counterclockwise. So to turn `form` 30&deg; to the left\nyou would say, `(rotate (degrees 30) form)`.\n"
-        },
-        { "name" : "scale",
-          "type" : "Float -> Form -> Form",
-          "desc" : "Scale a form by a given factor. Scaling by 2 doubles the size.\n"
-        },
-        { "name" : "move",
-          "type" : "(Float,Float) -> Form -> Form",
-          "desc" : "Move a form by the given amount. This is a relative translation so\n`(move (10,10) form)` would move `form` ten pixels up and ten pixels to the\nright.\n"
-        },
-        { "name" : "moveX",
-          "type" : "Float -> Form -> Form",
-          "desc" : "Move a shape in the x direction. This is relative so `(moveX 10 form)` moves\n`form` 10 pixels to the right.\n"
-        },
-        { "name" : "moveY",
-          "type" : "Float -> Form -> Form",
-          "desc" : "Move a shape in the y direction. This is relative so `(moveY 10 form)` moves\n`form` upwards by 10 pixels.\n"
-        },
-        { "name" : "collage",
-          "type" : "Int -> Int -> [Form] -> Element",
-          "desc" : "A collage is a collection of 2D forms. There are no strict positioning\nrelationships between forms, so you are free to do all kinds of 2D graphics.\n"
-        },
-        { "name" : "Path",
-          "type" : "type Path = [(Float,Float)]",
-          "desc" : ""
-        },
-        { "name" : "path",
-          "type" : "[(Number a,Number a)] -> Path",
-          "desc" : "Create a path that follows a sequence of points.\n"
-        },
-        { "name" : "segment",
-          "type" : "(Number a,Number a) -> (Number a,Number a) -> Path",
-          "desc" : "Create a path along a given line segment.\n"
-        },
-        { "name" : "Shape",
-          "type" : "type Shape = [(Float,Float)]",
-          "desc" : ""
-        },
-        { "name" : "polygon",
-          "type" : "[(Number a,Number a)] -> Shape",
-          "desc" : "Create an arbitrary polygon by specifying its corners in order.\n`polygon` will automatically close all shapes, so the given list\nof points does not need to start and end with the same position.\n"
-        },
-        { "name" : "rect",
-          "type" : "Number a -> Number a -> Shape",
-          "desc" : "A rectangle with a given width and height.\n"
-        },
-        { "name" : "square",
-          "type" : "Number a -> Shape",
-          "desc" : "A square with a given edge length.\n"
-        },
-        { "name" : "oval",
-          "type" : "Number a -> Number a -> Shape",
-          "desc" : "An oval with a given width and height.\n"
-        },
-        { "name" : "circle",
-          "type" : "Number a -> Shape",
-          "desc" : "A circle with a given radius.\n"
-        },
-        { "name" : "ngon",
-          "type" : "Int -> Number a -> Shape",
-          "desc" : "A regular polygon with N sides. The first argument specifies the number\nof sides and the second is the radius. So to create a pentagon with radius\n30 you would say:\n\n        ngon 5 30\n"
-        }
-      ]
-    }
-  ]
-}
diff --git a/elm-runtime.js b/elm-runtime.js
deleted file mode 100644
--- a/elm-runtime.js
+++ /dev/null
@@ -1,5152 +0,0 @@
-Elm = {}; Elm.Native = {}; Elm.Native.Graphics = {};
-Elm.Graphics = {}; ElmRuntime = {}; ElmRuntime.Render = {}
-
-Elm.Native.Utils = function(elm) {
-  'use strict';
-
-  elm.Native = elm.Native || {};
-  if (elm.Native.Utils) return elm.Native.Utils;
-
-  function eq(x,y) {
-    if (x === y) return true;
-    if (typeof x === "object") {
-      var c = 0;
-      for (var i in x) { ++c; if (!eq(x[i],y[i])) return false; }
-      return c === Object.keys(y).length;
-    }
-    if (typeof x === 'function') {
-      throw new Error('Equality error: general function equality is ' +
-      'undecidable, and therefore, unsupported');
-    }
-    return x === y;
-  }
-
-  var EQ = 0, LT = 1, GT = 2, ord = ['EQ','LT','GT'];
-  function compare(x,y) { return { ctor: ord[cmp(x,y)] } }
-  function cmp(x,y) {
-    var ord;
-    if (typeof x !== 'object') return x === y ? EQ : x < y ? LT : GT;
-
-    if (x.ctor === "Cons" || x.ctor === "Nil") {
-      while (true) {
-          if (x.ctor === "Nil" && y.ctor === "Nil") return EQ;
-          if (x.ctor !== y.ctor) return x.ctor === 'Nil' ? LT : GT;
-          ord = cmp(x._0, y._0);
-          if (ord !== EQ) return ord;
-          x = x._1;
-          y = y._1;
-      }
-    }
-
-    if (x.ctor.slice(0,5) === 'Tuple') {
-      var n = x.ctor.slice(5) - 0;
-      var err = 'cannot compare tuples with more than 6 elements.';
-      if (n === 0) return EQ;
-      if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
-      if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
-      if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
-      if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
-      if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
-      if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
-      if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
-      return EQ;
-    }
-    throw new Error('Comparison error: comparison is only defined on ints, ' +
-        'floats, times, chars, strings, lists of comparable values, ' +
-        'and tuples of comparable values.')
-  }
-
-
-  var Tuple0 = { ctor: "Tuple0" };
-  function Tuple2(x,y) { return { ctor:"Tuple2", _0:x, _1:y } }
-
-  var count = 0;
-  function guid(_) { return count++ }
-
-  function copy(r) {
-    var o = {};
-    for (var i in r) { o[i] = r[i]; }
-    return o;
-  }
-
-  function remove(x,r) {
-    var o = copy(r);
-    if (x in o._) {
-      o[x] = o._[x][0];
-      o._[x] = o._[x].slice(1);
-      if (o._[x].length === 0) { delete o._[x]; }
-    } else {
-      delete o[x];
-    }
-    return o;
-  }
-
-  function replace(kvs,r) {
-    var o = copy(r);
-    for (var i = kvs.length; i--; ) {
-      var kvsi = kvs[i];
-      o[kvsi[0]] = kvsi[1];
-    }
-    return o;
-  }
-
-  function insert(x,v,r) {
-    var o = copy(r);
-    if (x in o) o._[x] = [o[x]].concat(x in o._ ? o._[x].slice(0) : []);
-    o[x] = v;
-    return o;
-  }
-
-  function max(a,b) { return a > b ? a : b }
-  function min(a,b) { return a < b ? a : b }
-
-  function mod(a,b) {
-    var r = a % b;
-    var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r+b) : -mod(-a,-b));
-
-    return m === b ? 0 : m;
-  }
-
-  function htmlHeight(width, html) {
-    var t = document.createElement('div');
-    t.innerHTML = html;
-    if (width > 0) { t.style.width = width + "px"; }
-    t.style.visibility = "hidden";
-    t.style.styleFloat = "left";
-    t.style.cssFloat   = "left";
-
-    elm.node.appendChild(t);
-    var style = window.getComputedStyle(t, null);
-    var w = Math.ceil(style.getPropertyValue("width").slice(0,-2) - 0);
-    var h = Math.ceil(style.getPropertyValue("height").slice(0,-2) - 0);
-    elm.node.removeChild(t);
-    return Tuple2(w,h);
-  }
-
-  function adjustOffset() {
-      var node = elm.node;
-      var offsetX = 0, offsetY = 0;
-      if (node.offsetParent) {
-          do {
-              offsetX += node.offsetLeft;
-              offsetY += node.offsetTop;
-          } while (node = node.offsetParent);
-      }
-      elm.node.offsetX = offsetX;
-      elm.node.offsetY = offsetY;
-  }
-
-  if (elm.display === ElmRuntime.Display.COMPONENT) {
-      elm.node.addEventListener('mouseover', adjustOffset);
-  }
-
-  return elm.Native.Utils = {
-      eq:eq,
-      cmp:compare,
-      compare:F2(compare),
-      Tuple0:Tuple0,
-      Tuple2:Tuple2,
-      copy: copy,
-      remove: remove,
-      replace: replace,
-      insert: insert,
-      guid: guid,
-      max : F2(max),
-      min : F2(min),
-      mod : F2(mod),
-      htmlHeight: F2(htmlHeight),
-      toFloat: function(x){return x}
-  };
-};
-
-Elm.Native.Text = function(elm) {
-  'use strict';
-
-  elm.Native = elm.Native || {};
-  if (elm.Native.Text) return elm.Native.Text;
-
-  var JS = Elm.JavaScript(elm);
-  var htmlHeight = Elm.Native.Utils(elm).htmlHeight;
-  var Color = Elm.Native.Color(elm);
-  var Element = Elm.Graphics.Element(elm);
-  var show = Elm.Native.Show(elm).show;
-
-  function makeSpaces(s) {
-    if (s.length == 0) { return s; }
-    var arr = s.split('');
-    if (arr[0] == ' ') { arr[0] = "&nbsp;" }      
-    for (var i = arr.length; --i; ) {
-      if (arr[i][0] == ' ' && arr[i-1] == ' ') {
-        arr[i-1] = arr[i-1] + arr[i];
-        arr[i] = '';
-      }
-    }
-    for (var i = arr.length; i--; ) {
-      if (arr[i].length > 1 && arr[i][0] == ' ') {
-        var spaces = arr[i].split('');
-        for (var j = spaces.length - 2; j >= 0; j -= 2) {
-          spaces[j] = '&nbsp;';
-        }
-        arr[i] = spaces.join('');
-      }
-    }
-    arr = arr.join('');
-    if (arr[arr.length-1] === " ") {
-	return arr.slice(0,-1) + '&nbsp;';
-    }
-    return arr;
-  }
-
-  function properEscape(str) {
-    if (str.length == 0) return str;
-    str = str //.replace(/&/g,  "&#38;")
-	.replace(/"/g, /*"*/ '&#34;')
-	.replace(/'/g, /*'*/ "&#39;")
-	.replace(/</g,  "&#60;")
-	.replace(/>/g,  "&#62;")
-	.replace(/\n/g, "<br/>");
-    var arr = str.split('<br/>');
-    for (var i = arr.length; i--; ) {
-	arr[i] = makeSpaces(arr[i]);
-    }
-    return arr.join('<br/>');
-  }
-
-  function toText(str) { return properEscape(JS.fromString(str)); }
-
-  function addTag(tag) { return function(text) {
-      return '<' + tag + ' style="padding:0;margin:0">' + text + '</' + tag + '>';
-    }
-  }
-  
-  function addStyle(style, value, text) {
-    return "<span style='" + style + ":" + value + "'>" + text + "</span>";
-  }
-
-  function typeface(name, text) {
-    return addStyle('font-family', JS.fromString(name), text);
-  }
-  function monospace(text) {
-    return addStyle('font-family', 'monospace', text);
-  }
-  function size(px, text) { return addStyle('font-size', px + 'px', text) }
-  var header = addTag('h1');
-  function height(h, text) { return addStyle('font-size', h+'em', text) }
-  function italic(text) { return addStyle('font-style', 'italic', text) }
-  var bold = addTag('b');
-
-  function extract(c) {
-    if (c._3 === 1) { return 'rgb(' + c._0 + ',' + c._1 + ',' + c._2 + ')'; }
-    return 'rgba(' + c._0 + ',' + c._1 + ',' + c._2 + ',' + c._3 + ')';
-  }
-  function color(c, text) {
-    return addStyle('color', extract(c), text);
-  }
-  function underline(text) { return addStyle('text-decoration', 'underline', text) }
-  function overline(text) { return addStyle('text-decoration', 'overline', text) }
-  function strikeThrough(text) {
-      return addStyle('text-decoration', 'line-through', text);
-  }
-  function link(href, text) {
-    return "<a href='" + toText(href) + "'>" + text + "</a>";
-  }
-
-  function position(pos) { return function(text) {
-    var e = {ctor:'RawHtml',
-	     _0: '<div style="padding:0;margin:0;text-align:' +
-                   pos + '">' + text + '</div>'
-            };
-    var p = A2(htmlHeight, 0, text);
-    return A3(Element.newElement, p._0, p._1, e);
-   }
-  }
-
-  function asText(v) {
-      return position('left')(monospace(toText(show(v))));
-  }
-
-  function plainText(v) {
-      return position('left')(toText(v));
-  }
-
-  return elm.Native.Text = {
-      toText: toText,
-
-      header : header,
-      height : F2(height),
-      italic : italic,
-      bold : bold,
-      underline : underline,
-      overline : overline,
-      strikeThrough : strikeThrough,
-      monospace : monospace,
-      typeface : F2(typeface),
-      color : F2(color),
-      link : F2(link),
-
-      justified : position('justify'),
-      centered : position('center'),
-      righted : position('right'),
-      text : position('left'),
-      plainText : plainText,
-
-      asText : asText
-  };
-
-};
-Elm.Native.Show = function(elm) {
-    'use strict';
-
-    elm.Native = elm.Native || {};
-    if (elm.Native.Show) return elm.Native.Show;
-
-    var NList = Elm.Native.List(elm);
-    var List = Elm.List(elm);
-    var Maybe = Elm.Maybe(elm);
-    var JS = Elm.JavaScript(elm);
-    var Dict = Elm.Dict(elm);
-    var Json = Elm.Json(elm);
-    var Tuple2 = Elm.Native.Utils(elm).Tuple2;
-
-    var toString = function(v) {
-        if (typeof v === "function") {
-            var name = v.func ? v.func.name : v.name;
-            return '<function' + (name === '' ? '' : ': ') + name + '>';
-        } else if (typeof v === "boolean") {
-            return v ? "True" : "False";
-        } else if (typeof v === "number") {
-            return v+"";
-        } else if (typeof v === "string" && v.length < 2) {
-            return "'" + showChar(v) + "'";
-        } else if (typeof v === "object" && '_' in v) {
-            var output = [];
-            for (var k in v._) {
-                for (var i = v._[k].length; i--; ) {
-                    output.push(k + " = " + toString(v._[k][i]));
-                }
-            }
-            for (var k in v) {
-                if (k === '_') continue;
-                output.push(k + " = " + toString(v[k]));
-            }
-            if (output.length === 0) return "{}";
-            return "{ " + output.join(", ") + " }";
-        } else if (typeof v === "object" && 'ctor' in v) {
-            if (v.ctor.substring(0,5) === "Tuple") {
-                var output = [];
-                for (var k in v) {
-                    if (k === 'ctor') continue;
-                    output.push(toString(v[k]));
-                }
-                return "(" + output.join(",") + ")";
-            } else if (v.ctor === "Cons") {
-                var isStr = typeof v._0 === "string",
-                start = isStr ? '"' : "[",
-                end   = isStr ? '"' : "]",
-                sep   = isStr ?  "" : ",",
-                f     = !isStr ? toString : showChar;
-                var output = start + f(v._0);
-                v = v._1;
-                while (v.ctor === "Cons") {
-                    output += sep + f(v._0);
-                    v = v._1;
-                }
-                return output + end;
-            } else if (v.ctor === "Nil") {
-                return "[]";
-            } else if (v.ctor === "RBNode" || v.ctor === "RBEmpty") {
-                var cons = F3(function(k,v,acc){return NList.Cons(Tuple2(k,v),acc)});
-                var list = A3(Dict.foldr, cons, NList.Nil, v);
-                var name = "Dict";
-                if (list.ctor === "Cons" && list._0._1.ctor === "Tuple0") {
-                    name = "Set";
-                    list = A2(List.map, function(x){return x._0}, list);
-                }
-                return name + ".fromList " + toString(list);
-            } else {
-                var output = "";
-                for (var i in v) {
-                    if (i === 'ctor') continue;
-                    var str = toString(v[i]);
-                    var parenless = str[0] === '{' || str.indexOf(' ') < 0;
-                    output += ' ' + (parenless ? str : '(' + str + ')');
-                }
-                return v.ctor + output;
-            }
-        }
-        return v+"";
-    };
-    function show(v) { return NList.fromArray(toString(v)); }
-
-    function showChar (c) {
-        return c === '\n' ? '\\n' :
-               c === '\t' ? '\\t' :
-               c === '\b' ? '\\b' :
-               c === '\r' ? '\\r' :
-               c === '\v' ? '\\v' :
-               c === '\0' ? '\\0' :
-               c === '\'' ? "\\'" :
-               c === '\"' ? '\\"' :
-               c === '\\' ? '\\\\' : c;
-    }
-
-    return elm.Native.Show = { show:show };
-};
-
-Elm.Native.Prelude = function(elm) {
-  'use strict';
-  if (elm.Native.Prelude) return elm.Native.Prelude;
-
-  var JS = Elm.JavaScript(elm);
-  var Maybe = Elm.Maybe(elm);
-  var Utils = Elm.Native.Utils(elm);
-  var Char = Elm.Char(elm);
-
-  function div(a,b) { return (a/b)|0; }
-  function rem(a,b) { return a % b; }
-  var mod = Utils.mod;
-  function abs(x) { return x < 0 ? -x : x; }
-  function logBase(base,n) { return Math.log(n) / Math.log(base); }
-  function min(a,b) { return a < b ? a : b; }
-  function max(a,b) { return a > b ? a : b; }
-  function clamp(lo,hi,n) { return n < lo ? lo : n > hi ? hi : n; }
-  function xor(a,b) { return a !== b; }
-  function not(b) { return !b; }
-
-  function truncate(n) { return n|0; }
-
-  function id(n) { return n; }
-  function flip(f,a,b) { return A2(f,b,a); }
-  function curry(f,a,b) { return f(Utils.Tuple2(a,b)); }
-  function uncurry(f,v) { return A2(f,v._0,v._1); }
-  function fst(t) { return t._0; }
-  function snd(t) { return t._1; }
-
-  function readInt(str) {
-    var s = JS.fromString(str);
-    var len = s.length;
-    if (len === 0) { return Maybe.Nothing; }
-    var start = 0;
-    if (s[0] == '-') {
-      if (len === 1) { return Maybe.Nothing; }
-      start = 1;
-    }
-    for (var i = start; i < len; ++i) {
-      if (!Char.isDigit(s[i])) { return Maybe.Nothing; }
-    }
-    return Maybe.Just(parseInt(s, 10));
-  }
-
-  function readFloat(str) {
-    var s = JS.fromString(str);
-    var len = s.length;
-    if (len === 0) { return Maybe.Nothing; }
-    var start = 0;
-    if (s[0] == '-') {
-      if (len === 1) { return Maybe.Nothing; }
-      start = 1;
-    }
-    var dotCount = 0;
-    for (var i = start; i < len; ++i) {
-      if (Char.isDigit(s[i])) { continue; }
-      if (s[i] === '.') {
-        dotCount += 1;
-        if (dotCount <= 1) { continue; }
-      }
-      return Maybe.Nothing;
-    }
-    return Maybe.Just(parseFloat(s));
-  }
-
-  var prelude = {
-      div:F2(div),
-      rem:F2(rem),
-      mod:mod,
-
-      pi:Math.PI,
-      e:Math.e,
-      cos:Math.cos,
-      sin:Math.sin,
-      tan:Math.tan,
-      acos:Math.acos,
-      asin:Math.asin,
-      atan:Math.atan,
-      atan2:F2(Math.atan2),
-
-      sqrt:Math.sqrt,
-      abs:abs,
-      logBase:F2(logBase),
-      min:F2(min),
-      max:F2(max),
-      clamp:F3(clamp),
-      compare:Utils.compare,
-
-      xor:F2(xor),
-      not:not,
-      otherwise:true,
-
-      truncate:truncate,
-      ceiling:Math.ceil,
-      floor:Math.floor,
-      round:Math.round,
-      toFloat:id,
-
-      readInt:readInt,
-      readFloat:readFloat,
-
-      id:id,
-      flip:F3(flip),
-      curry:F3(curry),
-      uncurry:F2(uncurry),
-      fst:fst,
-      snd:snd
-  };
-
-  function add(Module) {
-    var M = Module(elm);
-    for (var k in M) { prelude[k] = M[k]; }
-  }
-  add(Elm.Native.Show);
-  add(Elm.Signal);
-  add(Elm.List);
-  add(Elm.Maybe);
-  add(Elm.Time);
-  add(Elm.Graphics.Element);
-
-  return elm.Native.Prelude = prelude;
-};
-
-Elm.Native.Matrix2D = function(elm) {
- "use strict";
-
- elm.Native = elm.Native || {};
- if (elm.Native.Matrix2D) return elm.Native.Matrix2D;
-
- var A;
- if (typeof Float32Array === 'undefined') {
-     A = function(arr) {
-         this.length = arr.length;
-         this[0] = arr[0];
-         this[1] = arr[1];
-         this[2] = arr[2];
-         this[3] = arr[3];
-         this[4] = arr[4];
-         this[5] = arr[5];
-     };
- } else {
-     A = Float32Array;
- }
-
- // layout of matrix in an array is
- //
- //   | m11 m12 dx |
- //   | m21 m22 dy |
- //   |  0   0   1 |
- //
- //  new A([ m11, m12, dx, m21, m22, dy ])
-
- var identity = new A([1,0,0,0,1,0]);
- function matrix(m11, m12, m21, m22, dx, dy) {
-     return new A([m11, m12, dx, m21, m22, dy]);
- }
- function rotation(t) {
-     var c = Math.cos(t);
-     var s = Math.sin(t);
-     return new A([c, -s, 0, s, c, 0]);
- }
-
- function rotate(t,m) {
-     var c = Math.cos(t);
-     var s = Math.sin(t);
-     var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4];
-     return new A([m11*c + m12*s, -m11*s + m12*c, m[2],
-                   m21*c + m22*s, -m21*s + m22*c, m[5]]);
- }
- /*
- function move(xy,m) {
-     var x = xy._0;
-     var y = xy._1;
-     var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4];
-     return new A([m11, m12, m11*x + m12*y + m[2],
-                   m21, m22, m21*x + m22*y + m[5]]);
- }
- function scale(s,m) { return new A([m[0]*s, m[1]*s, m[2], m[3]*s, m[4]*s, m[5]]); }
- function scaleX(x,m) { return new A([m[0]*x, m[1], m[2], m[3]*x, m[4], m[5]]); }
- function scaleY(y,m) { return new A([m[0], m[1]*y, m[2], m[3], m[4]*y, m[5]]); }
- function reflectX(m) { return new A([-m[0], m[1], m[2], -m[3], m[4], m[5]]); }
- function reflectY(m) { return new A([m[0], -m[1], m[2], m[3], -m[4], m[5]]); }
-
- function transform(m11, m21, m12, m22, mdx, mdy, n) {
-     var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5];
-     return new A([m11*n11 + m12*n21,
-                   m11*n12 + m12*n22,
-                   m11*ndx + m12*ndy + mdx,
-                   m21*n11 + m22*n21,
-                   m21*n12 + m22*n22,
-                   m21*ndx + m22*ndy + mdy]);
- }
- */
- function multiply(m, n) {
-     var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4], mdx = m[2], mdy = m[5];
-     var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5];
-     return new A([m11*n11 + m12*n21,
-                   m11*n12 + m12*n22,
-                   m11*ndx + m12*ndy + mdx,
-                   m21*n11 + m22*n21,
-                   m21*n12 + m22*n22,
-                   m21*ndx + m22*ndy + mdy]);
- }
-
- return elm.Native.Matrix2D = {
-     identity:identity,
-     matrix:F6(matrix),
-     rotation:rotation,
-     multiply:F2(multiply)
-     /*
-     transform:F7(transform),
-     rotate:F2(rotate),
-     move:F2(move),
-     scale:F2(scale),
-     scaleX:F2(scaleX),
-     scaleY:F2(scaleY),
-     reflectX:reflectX,
-     reflectY:reflectY
-     */
- };
-
-};
-Elm.Native.List = function(elm) {
-  "use strict";
-
-  elm.Native = elm.Native || {};
-  if (elm.Native.List) return elm.Native.List;
-  if ('values' in Elm.Native.List)
-      return elm.Native.List = Elm.Native.List.values;
-
-  var Utils = Elm.Native.Utils(elm);
-
-  // TODO: Improve Nil handling
-  // We can change places like:  if (xs.ctor === 'Nil') ... to if (xs === Nil) ...
-  // but only if we're confident Nil can only be defined once.
-  // Currently (27Mar2013) each module can have different instantiations, so multiple Nil objects can exist
-  // (and if they're used interchangeably then direct object comparison fails where ctor doesn't).
-  // So, this can only be fixed when modules initialisation is also fixed.
-  // The performance overhead of the .ctor calls is 5-10% according to jsperf (depending on fn + list size)
-  // (on firefox 19)
-
-  var Nil = { ctor:'Nil' };
-
-  // using freeze for every cons would be nice but is a huge (9x on firefox 19)
-  // performance penalty
-  function Cons(hd,tl) { return { ctor:"Cons", _0:hd, _1:tl }; }
-
-  function throwError(f) {
-    throw new Error("Function '" + f + "' expects a non-empty list!");
-  }
-
-  function toArray(xs) {
-    var out = [];
-    while (xs.ctor !== 'Nil') {
-      out.push(xs._0);
-      xs = xs._1;
-    }
-    return out;
-  }
-
-  function fromArray(arr) {
-    var out = Nil;
-    for (var i = arr.length; i--; ) {
-      out = Cons(arr[i], out);
-    }
-    return out;
-  }
-
-  function range(lo,hi) {
-    var lst = Nil;
-    if (lo <= hi) {
-      do { lst = Cons(hi,lst) } while (hi-->lo);
-    }
-    return lst
-  }
-
-  function append(xs,ys) {
-    if (typeof xs === "string") { return xs.concat(ys); }
-    if (xs.ctor === 'Nil') { return ys; }
-    var root = Cons(xs._0, Nil);
-    var curr = root;
-    xs = xs._1;
-    while (xs.ctor !== 'Nil') {
-	curr._1 = Cons(xs._0, Nil);
-	xs = xs._1;
-	curr = curr._1;
-    }
-    curr._1 = ys;
-    return root;
-  }
-
-  function head(v) { return v.ctor === 'Nil' ? throwError('head') : v._0; }
-  function tail(v) { return v.ctor === 'Nil' ? throwError('tail') : v._1; }
-
-  function last(xs) {
-    if (xs.ctor === 'Nil') { throwError('last'); }
-    var out = xs._0;
-    while (xs.ctor !== 'Nil') {
-      out = xs._0;
-      xs = xs._1;
-    }
-    return out;
-  }
-
-  function map(f, xs) {
-    var arr = [];
-    while (xs.ctor !== 'Nil') {
-      arr.push(f(xs._0));
-      xs = xs._1;
-    }
-    return fromArray(arr);
-  }
-
-   // f defined similarly for both foldl and foldr (NB: different from Haskell)
-   // ie, foldl :: (a -> b -> b) -> b -> [a] -> b
-  function foldl(f, b, xs) {
-    var acc = b;
-    while (xs.ctor !== 'Nil') {
-      acc = A2(f, xs._0, acc);
-      xs = xs._1;
-    }
-    return acc;
-  }
-
-  function foldr(f, b, xs) {
-    var arr = toArray(xs);
-    var acc = b;
-    for (var i = arr.length; i--; ) {
-      acc = A2(f, arr[i], acc);
-    }
-    return acc;
-  }
-
-  function foldl1(f, xs) {
-    return xs.ctor === 'Nil' ? throwError('foldl1') : foldl(f, xs._0, xs._1);
-  }
-
-  function foldr1(f, xs) {
-    if (xs.ctor === 'Nil') { throwError('foldr1'); }
-    var arr = toArray(xs);
-    var acc = arr.pop();
-    for (var i = arr.length; i--; ) {
-      acc = A2(f, arr[i], acc);
-    }
-    return acc;
-  }
-
-  function scanl(f, b, xs) {
-    var arr = toArray(xs);
-    arr.unshift(b);
-    var len = arr.length;
-    for (var i = 1; i < len; ++i) {
-      arr[i] = A2(f, arr[i], arr[i-1]);
-    }
-    return fromArray(arr);
-  }
-
-  function scanl1(f, xs) {
-    return xs.ctor === 'Nil' ? throwError('scanl1') : scanl(f, xs._0, xs._1);
-  }
-
-  function filter(pred, xs) {
-    var arr = [];
-    while (xs.ctor !== 'Nil') {
-      if (pred(xs._0)) { arr.push(xs._0); }
-      xs = xs._1;
-    }
-    return fromArray(arr);
-  }
-
-  function length(xs) {
-    var out = 0;
-    while (xs.ctor !== 'Nil') {
-      out += 1;
-      xs = xs._1;
-    }
-    return out;
-  }
-
-  function member(x, xs) {
-    while (xs.ctor !== 'Nil') {
-      if (Utils.eq(x,xs._0)) return true;
-      xs = xs._1;
-    }
-    return false;
-  }
-
-  function reverse(xs) { return fromArray(toArray(xs).reverse()); }
-
-  function concat(xss) {
-      if (xss.ctor === 'Nil') return xss;
-      var arr = toArray(xss);
-      var xs = arr[arr.length-1];
-      for (var i = arr.length-1; i--; ) {
-	  xs = append(arr[i], xs);
-      }
-      return xs;
-  }
-
-  function all(pred, xs) {
-    while (xs.ctor !== 'Nil') {
-      if (!pred(xs._0)) return false;
-      xs = xs._1;
-    }
-    return true;
-  }
-
-  function any(pred, xs) {
-    while (xs.ctor !== 'Nil') {
-      if (pred(xs._0)) return true;
-      xs = xs._1;
-    }
-    return false;
-  }
-
-  function zipWith(f, xs, ys) {
-    var arr = [];
-    while (xs.ctor !== 'Nil' && ys.ctor !== 'Nil') {
-      arr.push(A2(f, xs._0, ys._0));
-      xs = xs._1;
-      ys = ys._1;
-    }
-    return fromArray(arr);
-  }
-
-  function zip(xs, ys) {
-    var arr = [];
-    while (xs.ctor !== 'Nil' && ys.ctor !== 'Nil') {
-      arr.push(Utils.Tuple2(xs._0, ys._0));
-      xs = xs._1;
-      ys = ys._1;
-    }
-    return fromArray(arr);
-  }
-
-  function sort(xs) {
-    function cmp(a,b) {
-      var ord = Utils.compare(a,b).ctor;
-      return ord=== 'EQ' ? 0 : ord === 'LT' ? -1 : 1;
-    }
-    return fromArray(toArray(xs).sort(cmp));
-  }
-
-  function take(n, xs) {
-    var arr = [];
-    while (xs.ctor !== 'Nil' && n > 0) {
-      arr.push(xs._0);
-      xs = xs._1;
-      --n;
-    }
-    return fromArray(arr);
-  }
-
-  function drop(n, xs) {
-    while (xs.ctor !== 'Nil' && n > 0) {
-      xs = xs._1;
-      --n;
-    }
-    return xs;
-  }
-
-  function join(sep, xss) {
-    if (typeof sep === 'string') return toArray(xss).join(sep);
-    if (xss.ctor === 'Nil') return Nil;
-    var s = toArray(sep);
-    var out = toArray(xss._0);
-    xss = xss._1;
-    while (xss.ctor !== 'Nil') {
-      out = out.concat(s, toArray(xss._0));
-      xss = xss._1;
-    }
-    return fromArray(out);
-  }
-
-  function split(seperator, list) {
-    var array = toArray(list);
-    var alen = array.length;
-    if (alen === 0) {
-      // splitting an empty list is a list of lists: [[]]
-      return Cons(Nil,Nil);
-    }
-
-    var sep = toArray(seperator);
-    var seplen = sep.length;
-    if (seplen === 0) {
-      // splitting with an empty sep is a list of all elements
-      // Same as (map (\x -> [x]) list)
-      var out = Nil;
-      for (var i = alen; i--; ) {
-        out = Cons(Cons(array[i],Nil), out);
-      }
-      return out;
-    }
-
-    var matches = [-seplen];
-    var sepStart = sep[0];
-    var len = alen - seplen + 1;
-    for (var i = 0; i < len; ++i) {
-      if (Utils.eq(array[i], sepStart)) {
-        var match = true;
-        for (var j = seplen; --j; ) {
-          if (!Utils.eq(array[i+j], sep[j])) { match = false;  break; }
-        }
-        if (match) {
-          matches.push(i);
-          i += seplen - 1;
-        }
-      }
-    }
-
-    // shortcut in case of no matches
-    if (matches.length === 0) {
-      return Cons(list,Nil);
-    }
-
-    var out = Nil;
-    var index = alen - 1;
-    for (var i = matches.length; i--; ) {
-      var temp = Nil;
-      var stop = matches[i] + seplen - 1;
-      for ( ; index > stop; --index ) {
-        temp = Cons(array[index], temp);
-      }
-      out = Cons(temp,out);
-      index -= seplen;
-    }
-    return out;
-  }
-
-  Elm.Native.List.values = {
-      Nil:Nil,
-      Cons:Cons,
-      toArray:toArray,
-      fromArray:fromArray,
-      range:range,
-      append:append,
-
-      head:head,
-      tail:tail,
-      last:last,
-
-      map:F2(map),
-      foldl:F3(foldl),
-      foldr:F3(foldr),
-
-      foldl1:F2(foldl1),
-      foldr1:F2(foldr1),
-      scanl:F3(scanl),
-      scanl1:F2(scanl1),
-      filter:F2(filter),
-      length:length,
-      member:F2(member),
-      reverse:reverse,
-      concat:concat,
-
-      all:F2(all),
-      any:F2(any),
-      zipWith:F3(zipWith),
-      zip:F2(zip),
-      sort:sort,
-      take:F2(take),
-      drop:F2(drop),
-
-      join:F2(join),
-      split:F2(split)
-  };
-  return elm.Native.List = Elm.Native.List.values;
-
-};
-Elm.Native.Json = function(elm) {
-  'use strict';
-
-  var Maybe = Elm.Maybe(elm);
-  var Dict = Elm.Dict(elm);
-  var List = Elm.List(elm);
-  var JS = Elm.JavaScript(elm);
-  var Utils = Elm.Native.Utils(elm);
-
-  function fromValue(v) {
-    switch (v.ctor) {
-    case 'Null'   : return null;
-    case 'String' : return JS.fromString(v._0);
-    case 'Object' :
-      var obj = {};
-      var array = JS.fromList(Dict.toList(v._0));
-      for (var i = array.length; i--; ) {
-	obj[JS.fromString(array[i]._0)] = fromValue(array[i]._1);
-      }
-      return obj;
-    case 'Array'  :
-      var array = JS.fromList(v._0);
-      for (var i = array.length; i--; ) {
-	array[i] = fromValue(array[i]);
-      }
-      return array;
-    default :
-      return v._0;
-    }
-  }
-
-  function toPrettyJSString(sep, obj) {
-    return JSON.stringify(fromValue(obj), null, JS.fromString(sep));
-  }
-
-  function toValue(v) {
-    switch (typeof v) {
-    case 'string' : return { ctor:"String", _0: JS.toString(v) };
-    case 'number' : return { ctor:"Number", _0: JS.toFloat(v)  };
-    case 'boolean': return { ctor:"Bool"  , _0: JS.toBool(v)   };
-    case 'object' :
-      if (v === null) return { ctor:"Null" };
-      if (v instanceof Array) {
-          for (var i = v.length; i--; ) { v[i] = toValue(v[i]); }
-	  return { ctor:"Array", _0: JS.toList(v) };
-      }
-      var array = [];
-      for (var k in v) array.push(Utils.Tuple2(JS.toString(k), toValue(v[k])));
-      return { ctor:"Object", _0: Dict.fromList(JS.toList(array)) };
-    }
-  }
-
-  function fromJSString(str) {
-    try {
-	return Maybe.Just(toValue(JSON.parse(str)));
-    } catch (e) {
-	return Maybe.Nothing;
-    }
-  }
-
-  return elm.Native.Json = {
-      toJSString : F2(toPrettyJSString),
-      fromJSString : fromJSString,
-      toJSObject : fromValue,
-      fromJSObject : toValue
-  };
-
-};
-
-Elm.Native.JavaScript = function(elm) {
-  'use strict';
-
-  elm.Native = elm.Native || {};
-  if (elm.Native.JavaScript) return elm.Native.JavaScript;
-
-  var List = Elm.Native.List(elm);
-  var Render = ElmRuntime.use(ElmRuntime.Render.Element);
-
-  function fromJS(v) {
-    var type = typeof v;
-    if (type === 'number' ) return v;
-    if (type === 'boolean') return v;
-    if (type === 'string' ) return List.fromArray(v);
-    if (v instanceof Array) {
-      var arr = [];
-      var len = v.length;
-      for (var i = 0; i < len; ++i) {
-	var x = fromJS(v[i]);
-	if (x !== null) arr.push(x);
-      }
-      return List.fromArray(arr);
-    }
-    if (type === 'object') {
-      var rec = { _:{} };
-      for (var f in v) {
-	var x = fromJS(v[f]);
-	if (x !== null) rec[f] = x;
-      }
-      return rec;
-    }
-    return null;
-  }
-
-  function toJS(v) {
-    var type = typeof v;
-    if (type === 'number' || type === 'boolean') return v;
-    if (type === 'object' && '_' in v) {
-	var obj = {};
-	for (var k in v) {
-	    var x = v[k];
-	    if (x !== null) obj[k] = x;
-	}
-	return obj;
-    }
-    if (type === 'object' && (v.ctor === 'Cons' || v.ctor === 'Nil')) {
-	var array = List.toArray(v);
-	for (var i = array.length; i--; ) {
-	    array[i] = toJS(array[i]);
-	}
-	if (typeof array[0] === 'string') array.join('');
-	return array;
-    }
-    return null;
-  }
-  
-  function fromRecord(r) {
-    if (typeof r === 'object' && '_' in r) {
-      return toJS(r);
-    }
-    throw new Error("'fromRecord' must be called on a record.");
-  }
-
-  function id(n) { return n; }
-
-  function toElement(w,h,domNode) {
-      return A3( newElement, w, h, {
-              ctor: 'Custom',
-              type: 'DomNode',
-              render: function(node) { return node; },
-              update: function(node,oldNode,newNode) {
-                  if (node === newNode) return;
-                  node.parentNode.replaceChild(newNode, node);
-              },
-              model: domNode
-          });
-  }
-
-  function fromElement(element) {
-      return Render.render(element);
-  }
-
-  return elm.Native.JavaScript = {
-      toFloat    : id,
-      toBool     : id,
-      toInt      : function(n) { return n|0; },
-      toString   : List.fromArray,
-      toList     : List.fromArray,
-      fromString : function(s) { return List.toArray(s).join(''); },
-      fromList   : List.toArray,
-      fromInt    : id,
-      fromFloat  : id,
-      fromBool   : id,
-
-      toElement   : toElement,
-      fromElement : fromElement,
-      toRecord    : fromJS,
-      fromRecord  : fromRecord
-  };
-
-};
-function F2(fun) {
-  function wrapper(a) { return function(b) { return fun(a,b) } }
-  wrapper.arity = 2;
-  wrapper.func = fun;
-  return wrapper;
-}
-
-function F3(fun) {
-  function wrapper(a) {
-    return function(b) { return function(c) { return fun(a,b,c) }}
-  }
-  wrapper.arity = 3;
-  wrapper.func = fun;
-  return wrapper;
-}
-
-function F4(fun) {
-  function wrapper(a) { return function(b) { return function(c) {
-    return function(d) { return fun(a,b,c,d) }}}
-  }
-  wrapper.arity = 4;
-  wrapper.func = fun;
-  return wrapper;
-}
-
-function F5(fun) {
-  function wrapper(a) { return function(b) { return function(c) {
-    return function(d) { return function(e) { return fun(a,b,c,d,e) }}}}
-  }
-  wrapper.arity = 5;
-  wrapper.func = fun;
-  return wrapper;
-}
-
-function F6(fun) {
-  function wrapper(a) { return function(b) { return function(c) {
-    return function(d) { return function(e) { return function(f) {
-      return fun(a,b,c,d,e,f) }}}}}
-  }
-  wrapper.arity = 6;
-  wrapper.func = fun;
-  return wrapper;
-}
-
-function F7(fun) {
-  function wrapper(a) { return function(b) { return function(c) {
-    return function(d) { return function(e) { return function(f) {
-      return function(g) { return fun(a,b,c,d,e,f,g) }}}}}}
-  }
-  wrapper.arity = 7;
-  wrapper.func = fun;
-  return wrapper;
-}
-
-function F8(fun) {
-  function wrapper(a) { return function(b) { return function(c) {
-    return function(d) { return function(e) { return function(f) {
-	return function(g) { return function(h) {return fun(a,b,c,d,e,f,g,h)}}}}}}}
-  }
-  wrapper.arity = 8;
-  wrapper.func = fun;
-  return wrapper;
-}
-
-function F9(fun) {
-  function wrapper(a) { return function(b) { return function(c) {
-    return function(d) { return function(e) { return function(f) {
-	return function(g) { return function(h) { return function(i) {
-        return fun(a,b,c,d,e,f,g,h,i) }}}}}}}}
-  }
-  wrapper.arity = 9;
-  wrapper.func = fun;
-  return wrapper;
-}
-
-function A2(fun,a,b) {
-  return fun.arity === 2 ? fun.func(a,b) : fun(a)(b);
-}
-function A3(fun,a,b,c) {
-  return fun.arity === 3 ? fun.func(a,b,c) : fun(a)(b)(c);
-}
-function A4(fun,a,b,c,d) {
-  return fun.arity === 4 ? fun.func(a,b,c,d) : fun(a)(b)(c)(d);
-}
-function A5(fun,a,b,c,d,e) {
-  return fun.arity === 5 ? fun.func(a,b,c,d,e) : fun(a)(b)(c)(d)(e);
-}
-function A6(fun,a,b,c,d,e,f) {
-  return fun.arity === 6 ? fun.func(a,b,c,d,e,f) : fun(a)(b)(c)(d)(e)(f);
-}
-function A7(fun,a,b,c,d,e,f,g) {
-  return fun.arity === 7 ? fun.func(a,b,c,d,e,f,g) : fun(a)(b)(c)(d)(e)(f)(g);
-}
-function A8(fun,a,b,c,d,e,f,g,h) {
-  return fun.arity === 8 ? fun.func(a,b,c,d,e,f,g,h) : fun(a)(b)(c)(d)(e)(f)(g)(h);
-}
-function A9(fun,a,b,c,d,e,f,g,h,i) {
-  return fun.arity === 9 ? fun.func(a,b,c,d,e,f,g,h,i)
-                         : fun(a)(b)(c)(d)(e)(f)(g)(h)(i);
-}
-
-Elm.Native.Error = function(elm) {
-    'use strict';
-    elm.Native = elm.Native || {};
-    if (elm.Native.Error) return elm.Native.Error;
-
-    var fromString = Elm.Native.JavaScript(elm).fromString;
-
-    function Case(span) { 
-	var msg = 'Non-exhaustive pattern match in case expression'
-	throw new Error(msg + " (" + span + ")")
-    }
-
-    function If(span) { 
-	var msg = 'Non-exhaustive pattern match in multi-way-if expression'
-	throw new Error(msg + " (" + span + ")")
-    }
-
-    function raise(str) { throw new Error(fromString(str)); }
-
-    return elm.Native.Error = { Case: Case, If: If, raise: raise };
-};
-Elm.Native.Date = function(elm) {
- 'use strict';
-
- elm.Native = elm.Native || {};
- if (elm.Native.Date) return elm.Native.Date;
-
- var JS = Elm.JavaScript(elm);
- var Maybe = Elm.Maybe(elm);
-
- function dateNow() { return new window.Date; }
- function readDate(str) {
-     var d = new window.Date(JS.fromString(str));
-     if (isNaN(d.getTime())) return Maybe.Nothing;
-     return Maybe.Just(d);
- }
-
- var dayTable = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
- var monthTable = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
-		   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; 
-
- return elm.Native.Date = {
-     read    : readDate,
-     year    : function(d) { return d.getFullYear(); },
-     month   : function(d) { return { ctor:monthTable[d.getMonth()] }; },
-     day     : function(d) { return d.getDate(); },
-     hour    : function(d) { return d.getHours(); },
-     minute  : function(d) { return d.getMinutes(); },
-     second  : function(d) { return d.getSeconds(); },
-     toTime  : function(d) { return d.getTime(); },
-     dayOfWeek : function(d) { return { ctor:dayTable[d.getDay()] }; }
- };
-
-};
-
-
-Elm.Native.Color = function(elm) {
- "use strict";
-
- elm.Native = elm.Native || {};
- if (elm.Native.Color) return elm.Native.Color;
-
- var Utils = Elm.Native.Utils(elm);
-
- function complement(rgb) {
-     var hsv = toHSV(rgb);
-     hsv.hue = (hsv.hue + 180) % 360;
-     return toRGB(hsv);
- }
-
- function hsva(h,s,v,a) {
-     var degree = A2(Utils.mod, h * 180 / Math.PI, 360);
-     var clr = toRGB({hue:degree, saturation:s, value:v});
-     clr._3 = a;
-     return clr;
- }
-
- function hsv(h,s,v) {
-     var degree = A2(Utils.mod, h * 180 / Math.PI, 360);
-     return toRGB({hue:degree, saturation:s, value:v});
- }
-
- function toHSV(rgb) {
-  var hsv = {};
-  var r = rgb._0 / 255.0, g = rgb._1 / 255.0, b = rgb._2 / 255.0;
-  var M = Math.max(r,g,b);
-  var m = Math.min(r,g,b);
-  var c = M - m;
-
-  var h = 0;
-       if (c === 0) { h = 0; }
-  else if (M === r) { h = ((g - b) / c) % 6; }
-  else if (M === g) { h = ((b - r) / c) + 2; }
-  else if (M === b) { h = ((r - g) / c) + 4; }
-  h *= 60;
-
-  return { value : M, hue : h, saturation : (M === 0 ? 0 : c / M) };
- }
-
- function between(lo,hi,x) { return lo <= x && x < hi; }
- function norm(n) { return Math.round(n*255); }
-
- function toRGB(hsv) {
-  var c = hsv.value * hsv.saturation;
-  var hue = hsv.hue / 60;
-  var x = c * (1 - Math.abs((hue % 2) - 1));
-  var r = 0, g = 0, b = 0;
-       if (between(0,1,hue)) { r = c; g = x; b = 0; }
-  else if (between(1,2,hue)) { r = x; g = c; b = 0; }
-  else if (between(2,3,hue)) { r = 0; g = c; b = x; }
-  else if (between(3,4,hue)) { r = 0; g = x; b = c; }
-  else if (between(4,5,hue)) { r = x; g = 0; b = c; }
-  else if (between(5,6,hue)) { r = c; g = 0; b = x; }
-
-  var m = hsv.value - c;
-  return { ctor:"Color", _0:norm(r+m), _1:norm(g+m), _2:norm(b+m), _3:1 };
- }
-
- return elm.Native.Color = {
-    hsva:F4(hsva),
-    hsv:F3(hsv),
-    complement:complement
- };
-
-};
-Elm.Native.Char = function(elm) {
- 'use strict';
-
- elm.Native = elm.Native || {};
- if (elm.Native.Char) return elm.Native.Char;
-
- function isBetween(lo,hi) { return function(chr) {
-	 var c = chr.charCodeAt(0);
-	 return lo <= c && c <= hi;
-     };
- }
- var isDigit = isBetween('0'.charCodeAt(0),'9'.charCodeAt(0));
- var chk1 = isBetween('a'.charCodeAt(0),'f'.charCodeAt(0));
- var chk2 = isBetween('A'.charCodeAt(0),'F'.charCodeAt(0));
-
- return elm.Native.Char = {
-     fromCode : function(c) { return String.fromCharCode(c); },
-     toCode   : function(c) { return c.charCodeAt(0); },
-     toUpper  : function(c) { return c.toUpperCase(); },
-     toLower  : function(c) { return c.toLowerCase(); },
-     toLocaleUpper : function(c) { return c.toLocaleUpperCase(); },
-     toLocaleLower : function(c) { return c.toLocaleLowerCase(); },
-     isLower    : isBetween('a'.charCodeAt(0),'z'.charCodeAt(0)),
-     isUpper    : isBetween('A'.charCodeAt(0),'Z'.charCodeAt(0)),
-     isDigit    : isDigit,
-     isOctDigit : isBetween('0'.charCodeAt(0),'7'.charCodeAt(0)),
-     isHexDigit : function(c) { return isDigit(c) || chk1(c) || chk2(c); }
- };
-
-};
-
-Elm.Native.Window = function(elm) {
-  'use strict';
-
-  elm.Native = elm.Native || {};
-  if (elm.Native.Window) return elm.Native.Window;
-
-  var Signal = Elm.Signal(elm);
-  var Tuple2 = Elm.Native.Utils(elm).Tuple2;
-
-  function getWidth() { return elm.node.clientWidth; }
-  function getHeight() {
-      if (elm.display === ElmRuntime.Display.FULLSCREEN) {
-          return window.innerHeight;
-      }
-      return elm.node.clientHeight;
-  }
-
-  var dimensions = Signal.constant(Tuple2(getWidth(), getHeight()));
-  dimensions.defaultNumberOfKids = 2;
-
-  // Do not move width and height into Elm. By setting the default number of kids,
-  // the resize listener can be detached.
-  var width  = A2(Signal.lift, function(p){return p._0;}, dimensions);
-  width.defaultNumberOfKids = 0;
-
-  var height = A2(Signal.lift, function(p){return p._1;}, dimensions);
-  height.defaultNumberOfKids = 0;
-
-  function resizeIfNeeded() {
-      var w = getWidth();
-      var h = getHeight();
-      if (dimensions.value._0 === w && dimensions.value._1 === h) return;
-      var hasListener = elm.notify(dimensions.id, Tuple2(w,h));
-      if (!hasListener) window.removeEventListener('resize', resizeIfNeeded);
-  }
-  window.addEventListener('resize', resizeIfNeeded);
-
-  return elm.Native.Window = {
-      dimensions:dimensions,
-      width:width,
-      height:height,
-      resizeIfNeeded:resizeIfNeeded
-  };
-
-};
-
-Elm.Native.WebSocket = function(elm) {
-  'use strict';
-
-  elm.Native = elm.Native || {};
-  if (elm.Native.WebSocket) return elm.Native.WebSocket;
-
-  var Signal = Elm.Signal(elm);
-  var JS = Elm.JavaScript(elm);
-  var List = Elm.Native.List(elm);
-
-  function open(url, outgoing) {
-    var incoming = Signal.constant(List.Nil);
-    var ws = new WebSocket(JS.fromString(url));
-
-    var pending = [];
-    var ready = false;
-    
-    ws.onopen = function(e) {
-      var len = pending.length;
-      for (var i = 0; i < len; ++i) { ws.send(pending[i]); }
-      ready = true;
-    };
-    ws.onmessage = function(event) {
-      elm.notify(incoming.id, JS.toString(event.data));
-    };
-    
-    function send(msg) {
-      var s = JS.fromString(msg);
-      ready ? ws.send(s) : pending.push(s);
-    }
-    
-    function take1(x,y) { return x }
-    return A3(Signal.lift2, F2(take1), incoming, A2(Signal.lift, send, outgoing));
-  }
-
-  return elm.Native.WebSocket = { connect: F2(open) };
-};
-
-Elm.Native.Touch = function(elm) {
-  'use strict';
-
-  elm.Native = elm.Native || {};
-  if (elm.Native.Touch) return elm.Native.Touch;
-
-  var Signal = Elm.Signal(elm);
-  var JS = Elm.JavaScript(elm);
-  var _ = Elm.Native.Utils(elm);
-
-  function Dict() {
-    this.keys = [];
-    this.values = [];
-
-    this.insert = function(key,value) {
-      this.keys.push(key);
-      this.values.push(value);
-    };
-    this.lookup = function(key) {
-      var i = this.keys.indexOf(key)
-      return i >= 0 ? this.values[i] : {x:0,y:0,t:0};
-    };
-    this.remove = function(key) {
-      var i = this.keys.indexOf(key);
-      if (i < 0) return;
-      var t = this.values[i];
-      this.keys.splice(i,1);
-      this.values.splice(i,1);
-      return t;
-    };
-    this.clear = function() {
-        this.keys = [];
-        this.values = [];
-    };
-  }
-  
-  var root = Signal.constant([]),
-      tapTime = 500,
-      hasTap = false,
-      tap = {_:{},x:0,y:0},
-      dict = new Dict();
-
-  function touch(t) {
-      var r = dict.lookup(t.identifier);
-      return {_ : {},
-	      id: t.identifier,
-	      x : t.pageX - elm.node.offsetX,
-	      y : t.pageY - elm.node.offsetY,
-	      x0: r.x,
-	      y0: r.y,
-	      t0: r.t
-	      };
-  }
-
-  var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
-
-  function start(e) {
-    dict.insert(e.identifier,
-                {x: e.pageX - elm.node.offsetX,
-                 y: e.pageY - elm.node.offsetY,
-                 t: Date.now()});
-  }
-  function end(e) {
-    var t = dict.remove(e.identifier);
-    if (Date.now() - t.t < tapTime) {
-        hasTap = true;
-        tap = {_:{}, x:t.x, y:t.y};
-    }
-  }
-
-  function listen(name, f) {
-    function update(e) {
-      for (var i = e.changedTouches.length; i--; ) { f(e.changedTouches[i]); }
-      var ts = new Array(e.touches.length);
-      for (var i = e.touches.length; i--; ) { ts[i] = touch(e.touches[i]); }
-      var hasListener = elm.notify(root.id, ts);
-      if (!hasListener) return node.removeEventListener(name, update);
-      e.preventDefault();
-    }
-    node.addEventListener(name, update);
-  }
-
-  listen("touchstart", start);
-  listen("touchmove", function(_){});
-  listen("touchend", end);
-  listen("touchcancel", end);
-  listen("touchleave", end);
-
-  var mouseID = -1;
-  function move(e) {
-      for (var i = root.value.length; i--; ) {
-          if (root.value[i].id === mouseID) {
-              root.value[i].x = e.pageX - elm.node.offsetX;
-              root.value[i].y = e.pageY - elm.node.offsetY;
-              elm.notify(root.id, root.value);
-              break;
-          }
-      }
-  }
-  node.addEventListener("mousedown", function(e) {
-          node.addEventListener("mousemove", move);
-          e.identifier = mouseID;
-          start(e);
-          root.value.push(touch(e));
-          elm.notify(root.id, root.value);
-      });
-  node.addEventListener("mouseup", function(e) {
-          node.removeEventListener("mousemove", move);
-          e.identifier = mouseID;
-          end(e);
-          for (var i = root.value.length; i--; ) {
-              if (root.value[i].id === mouseID) {
-                  root.value.splice(i, 1);
-                  --mouseID;
-                  break;
-              }
-          }
-          elm.notify(root.id, root.value);
-      });
-  node.addEventListener("blur", function() {
-          node.removeEventListener("mousemove", move);
-          if (root.values.length > 0) {
-              elm.notify(root.id, []);
-              --mouseID;
-          }
-          dict.clear();
-      });
-
-  function dependency(f) {
-      var sig = A2( Signal.lift, f, root );
-      root.defaultNumberOfKids += 1;
-      sig.defaultNumberOfKids = 0;
-      return sig;
-  }
-
-  var touches = dependency(JS.toList);
-
-  var taps = function() {
-      var sig = dependency(function(_) { return tap; });
-      sig.defaultNumberOfKids = 1;
-      function pred(_) { var b = hasTap; hasTap = false; return b; }
-      var sig2 = A3( Signal.keepIf, pred, {_:{},x:0,y:0}, sig);
-      sig2.defaultNumberOfKids = 0;
-      return sig2;
-  }();
-
-  return elm.Native.Touch = { touches: touches, taps: taps };
-
-};
-Elm.Native.Time = function(elm) {
-  'use strict';
-
-  var Signal = Elm.Signal(elm);
-  var Maybe = Elm.Maybe(elm);
-  var Utils = Elm.Native.Utils(elm);
-
-  function fpsWhen(desiredFPS, isOn) {
-    var msPerFrame = 1000 / desiredFPS;
-    var prev = Date.now(), curr = prev, diff = 0, wasOn = true;
-    var ticker = Signal.constant(diff);
-    function tick(zero) { return function() {
-        curr = Date.now();
-        diff = zero ? 0 : curr - prev;
-        prev = curr;
-        elm.notify(ticker.id, diff);
-      };
-    }
-    var timeoutID = 0;
-    function f(isOn, t) {
-      if (isOn) {
-        timeoutID = setTimeout(tick(!wasOn && isOn), msPerFrame);
-      } else if (wasOn) {
-        clearTimeout(timeoutID);
-      }
-      wasOn = isOn;
-      return t;
-    }
-    return A3( Signal.lift2, F2(f), isOn, ticker );
-  }
-
-  function everyWhen(t, isOn) {
-    var clock = Signal.constant(Date.now());
-    function tellTime() { elm.notify(clock.id, Date.now()); }
-    setInterval(tellTime, t);
-    return clock;
-  }
-
-  function since(t, s) {
-    function cmp(a,b) { return !Utils.eq(a,b); }
-    var dcount = Signal.count(A2(Signal.delay, t, s));
-    return A3( Signal.lift2, F2(cmp), Signal.count(s), dcount );
-  }
-  function read(s) {
-      var t = Date.parse(s);
-      return isNaN(t) ? Maybe.Nothing : Maybe.Just(t);
-  }
-  return elm.Native.Time = {
-      fpsWhen : F2(fpsWhen),
-      fps : function(t) { return fpsWhen(t, Signal.constant(true)); },
-      every : function(t) { return everyWhen(t, Signal.constant(true)) },
-      delay : Signal.delay,
-      timestamp : Signal.timestamp,
-      since : F2(since),
-      toDate : function(t) { return new window.Date(t); },
-      read   : read
-  };
-
-};
-
-Elm.Native.Signal = function(elm) {
-  'use strict';
-
-  elm.Native = elm.Native || {};
-  if (elm.Native.Signal) return elm.Native.Signal;
-
-  var Utils  = Elm.Native.Utils(elm);
-  var foldl1 = Elm.List(elm).foldl1;
-
-  function send(node, timestep, changed) {
-    var kids = node.kids;
-    for (var i = kids.length; i--; ) {
-      kids[i].recv(timestep, changed, node.id);
-    }
-  }
-
-  function Input(base) {
-    this.id = Utils.guid();
-    this.value = base;
-    this.kids = [];
-    this.defaultNumberOfKids = 0;
-    this.recv = function(timestep, eid, v) {
-      var changed = eid === this.id;
-      if (changed) { this.value = v; }
-      send(this, timestep, changed);
-      return changed;
-    };
-    elm.inputs.push(this);
-  }
-
-  function LiftN(update, args) {
-    this.id = Utils.guid();
-    this.value = update();
-    this.kids = [];
-
-    var n = args.length;
-    var count = 0;
-    var isChanged = false;
-
-    this.recv = function(timestep, changed, parentID) {
-      ++count;
-      if (changed) { isChanged = true; }
-      if (count == n) {
-        if (isChanged) { this.value = update(); }
-        send(this, timestep, isChanged);
-        isChanged = false;
-        count = 0;
-      }
-    };
-    for (var i = n; i--; ) { args[i].kids.push(this); }
-  }
-
-  function lift(func, a) {
-    function update() { return func(a.value); }
-    return new LiftN(update, [a]);
-  }
-  function lift2(func, a, b) {
-    function update() { return A2( func, a.value, b.value ); }
-    return new LiftN(update, [a,b]);
-  }
-  function lift3(func, a, b, c) {
-    function update() { return A3( func, a.value, b.value, c.value ); }
-    return new LiftN(update, [a,b,c]);
-  }
-  function lift4(func, a, b, c, d) {
-    function update() { return A4( func, a.value, b.value, c.value, d.value ); }
-    return new LiftN(update, [a,b,c,d]);
-  }
-  function lift5(func, a, b, c, d, e) {
-    function update() { return A5( func, a.value, b.value, c.value, d.value, e.value ); }
-    return new LiftN(update, [a,b,c,d,e]);
-  }
-  function lift6(func, a, b, c, d, e, f) {
-    function update() { return A6( func, a.value, b.value, c.value, d.value, e.value, f.value ); }
-    return new LiftN(update, [a,b,c,d,e,f]);
-  }
-  function lift7(func, a, b, c, d, e, f, g) {
-    function update() { return A7( func, a.value, b.value, c.value, d.value, e.value, f.value, g.value ); }
-    return new LiftN(update, [a,b,c,d,e,f,g]);
-  }
-  function lift8(func, a, b, c, d, e, f, g, h) {
-    function update() { return A8( func, a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value ); }
-    return new LiftN(update, [a,b,c,d,e,f,g,h]);
-  }
-
-  function foldp(func,state,input) {
-    var first = true;
-    function update() {
-        first ? first = false : state = A2(func, input.value, state);
-        return state;
-    }
-    return new LiftN(update, [input]);
-  }
-
-  function DropIf(pred,base,input) {
-    this.id = Utils.guid();
-    this.value = pred(input.value) ? base : input.value;
-    this.kids = [];
-    this.recv = function(timestep, changed, parentID) {
-      var chng = changed && !pred(input.value);
-      if (chng) { this.value = input.value; }
-      send(this, timestep, chng);
-    };
-    input.kids.push(this);
-  }
-
-  function DropRepeats(input) {
-    this.id = Utils.guid();
-    this.value = input.value;
-    this.kids = [];
-    this.recv = function(timestep, changed, parentID) {
-      var chng = changed && !Utils.eq(this.value,input.value);
-      if (chng) { this.value = input.value; }
-      send(this, timestep, chng);
-    };
-    input.kids.push(this);
-  }
-
-  function dropWhen(s1,b,s2) {
-    var pairs = lift2( F2(function(x,y){return {x:x,y:y};}), s1, s2 );
-    var dropped = new DropIf(function(p){return p.x;},{x:true,y:b},pairs);
-    return lift(function(p){return p.y;}, dropped);
-  }
-
-  function timestamp(a) {
-    function update() { return Utils.Tuple2(Date.now(), a.value); }
-    return new LiftN(update, [a]);
-  }
-
-  function SampleOn(s1,s2) {
-    this.id = Utils.guid();
-    this.value = s2.value;
-    this.kids = [];
-
-    var count = 0;
-    var isChanged = false;
-
-    this.recv = function(timestep, changed, parentID) {
-      if (parentID === s1.id) isChanged = changed;
-      ++count;
-      if (count == 2) {
-        if (isChanged) { this.value = s2.value; }
-        send(this, timestep, isChanged);
-        count = 0;
-        isChanged = false;
-      }
-    };
-    s1.kids.push(this);
-    s2.kids.push(this);
-  }
-
-  function sampleOn(s1,s2) { return new SampleOn(s1,s2); }
-
-  function delay(t,s) {
-      var delayed = new Input(s.value);
-      var firstEvent = true;
-      function update(v) {
-        if (firstEvent) { firstEvent = false; return; }
-        setTimeout(function() { elm.notify(delayed.id, v); }, t);
-      }
-      function first(a,b) { return a; }
-      return new SampleOn(delayed, lift2(F2(first), delayed, lift(update,s)));
-  }
-
-  function Merge(s1,s2) {
-      this.id = Utils.guid();
-      this.value = s1.value;
-      this.kids = [];
-
-      var next = null;
-      var count = 0;
-      var isChanged = false;
-
-      this.recv = function(timestep, changed, parentID) {
-        ++count;
-        if (changed) {
-            isChanged = true;
-            if (parentID == s2.id && next === null) { next = s2.value; }
-            if (parentID == s1.id) { next = s1.value; }
-        }
-
-        if (count == 2) {
-            if (isChanged) { this.value = next; next = null; }
-            send(this, timestep, isChanged);
-            isChanged = false;
-            count = 0;
-        }
-      };
-      s1.kids.push(this);
-      s2.kids.push(this);
-  }
-
-  function merge(s1,s2) { return new Merge(s1,s2); }
-  function merges(ss) { return A2(foldl1, F2(merge), ss); }
-
-  return elm.Native.Signal = {
-    constant : function(v) { return new Input(v); },
-    lift  : F2(lift ),
-    lift2 : F3(lift2),
-    lift3 : F4(lift3),
-    lift4 : F5(lift4),
-    lift5 : F6(lift5),
-    lift6 : F7(lift6),
-    lift7 : F8(lift7),
-    lift8 : F9(lift8),
-    foldp : F3(foldp),
-    delay : F2(delay),
-    merge : F2(merge),
-    merges : merges,
-    count : function(s) { return foldp(F2(function(_,c) { return c+1; }), 0, s); },
-    countIf : F2(function(pred,s) {
-      return foldp(F2(function(x,c){
-        return pred(x) ? c+1 : c; }), 0, s)}),
-    keepIf : F3(function(pred,base,sig) {
-      return new DropIf(function(x) {return !pred(x);},base,sig); }),
-    dropIf : F3(function(pred,base,sig) { return new DropIf(pred,base,sig); }),
-    keepWhen : F3(function(s1,b,s2) {
-      return dropWhen(lift(function(b){return !b;},s1), b, s2); }),
-    dropWhen : F3(dropWhen),
-    dropRepeats : function(s) { return new DropRepeats(s);},
-    sampleOn : F2(sampleOn),
-    timestamp : timestamp
-  };
-};
-
-Elm.Native.Random = function(elm) {
-  'use strict';
-  elm.Native = elm.Native || {};
-  if (elm.Native.Random) return elm.Native.Random;
-
-  var Signal = Elm.Signal(elm);
-
-  function range(min, max, signal) {
-    function f(x) { return Math.floor(Math.random() * (max-min+1)) + min; }
-    return A2( Signal.lift, f, signal );
-  }
-
-  function flt(signal) {
-    function f(x) { return Math.random(); }
-    return A2( Signal.lift, f, signal );
-  }
-
-  elm.Native.Random = { range: F3(range) };
-  elm.Native.Random['float'] = flt;
-  return elm.Native.Random;
-
-};
-
-Elm.Native.Mouse = function(elm) {
-  'use strict';
-  elm.Native = elm.Native || {};
-  if (elm.Native.Mouse) return elm.Native.Mouse;
-
-  var Signal = Elm.Signal(elm);
-  var Utils = Elm.Native.Utils(elm);
-
-  var position  = Signal.constant(Utils.Tuple2(0,0));
-  position.defaultNumberOfKids = 2;
-
-  // do not move x and y into Elm. By setting their default number
-  // of kids, it is possible to detatch the mouse listeners if
-  // they are not needed.
-  var x = A2( Signal.lift, function(p){return p._0}, position);
-  x.defaultNumberOfKids = 0;
-  var y = A2( Signal.lift, function(p){return p._1}, position);
-  y.defaultNumberOfKids = 0;
-
-  var isDown    = Signal.constant(false);
-  var isClicked = Signal.constant(false);
-  var clicks = Signal.constant(Utils.Tuple0);
-
-  function getXY(e) {
-    var posx = 0;
-    var posy = 0;
-    if (!e) e = window.event;
-    if (e.pageX || e.pageY) {
-	posx = e.pageX;
-	posy = e.pageY;
-    } else if (e.clientX || e.clientY) 	{
-	posx = e.clientX + document.body.scrollLeft +
-	  document.documentElement.scrollLeft;
-	posy = e.clientY + document.body.scrollTop +
-	  document.documentElement.scrollTop;
-    }
-    return Utils.Tuple2(posx-elm.node.offsetX, posy-elm.node.offsetY);
-  }
-
-  var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
-
-  function click(e) {
-    var hasListener1 = elm.notify(isClicked.id, true);
-    var hasListener2 = elm.notify(clicks.id, Utils.Tuple0);
-    elm.notify(isClicked.id, false);
-    if (!hasListener1 && !hasListener2)
-	node.removeEventListener('click', click);
-  }
-
-  function down(e) {
-    var hasListener = elm.notify(isDown.id, true);
-    if (!hasListener) node.removeEventListener('mousedown', down);
-  }
-
-  function up(e) {
-    var hasListener = elm.notify(isDown.id, false);
-    if (!hasListener) node.removeEventListener('mouseup', up);
-  }
-
-  function move(e) {
-    var hasListener = elm.notify(position.id, getXY(e));
-    if (!hasListener) node.removeEventListener('mousemove', move);
-  }
-
-  node.addEventListener('click'    , click);
-  node.addEventListener('mousedown', down);
-  node.addEventListener('mouseup'  , up);
-  node.addEventListener('mousemove', move);
-
-  return elm.Native.Mouse = {
-      position: position,
-      x:x,
-      y:y,
-      isClicked: isClicked,
-      isDown: isDown,
-      clicks: clicks
-  };
-};
-Elm.Native.Keyboard = function(elm) {
-  'use strict';
-  elm.Native = elm.Native || {};
-  if (elm.Native.Keyboard) return elm.Native.Keyboard;
-
-  var Signal = Elm.Signal(elm);
-  var NList = Elm.Native.List(elm);
-
-  var keysDown = Signal.constant(NList.Nil);
-  var lastKey = Signal.constant('\0');
-
-  function down(e) {
-      if (NList.member(e.keyCode)(keysDown.value)) return;
-      var list = NList.Cons(e.keyCode, keysDown.value);
-      var hasListener = elm.notify(keysDown.id, list);
-      if (!hasListener) document.removeEventListener('keydown', down);
-  }
-  function up(e) {
-      function notEq(kc) { return kc !== e.keyCode; }
-      var codes = NList.filter(notEq)(keysDown.value);
-      var hasListener = elm.notify(keysDown.id, codes);
-      if (!hasListener) document.removeEventListener('keyup', up);
-  }
-  function blur(e) {
-      var hasListener = elm.notify(keysDown.id, NList.Nil);
-      if (!hasListener) document.removeEventListener('blur', blur);
-  }
-  function press(e) {
-      var hasListener = elm.notify(lastKey.id, e.charCode || e.keyCode);
-      if (!hasListener) document.removeEventListener('keypress', press);
-  }
-
-  document.addEventListener('keydown' , down );
-  document.addEventListener('keyup'   , up   );
-  document.addEventListener('blur'    , blur );
-  document.addEventListener('keypress', press);
-
-  function keySignal(f) {
-    var signal = A2( Signal.lift, f, keysDown );
-    keysDown.defaultNumberOfKids += 1;
-    signal.defaultNumberOfKids = 0;
-    return signal;
-  }
-
-  function dir(up, down, left, right) {
-    function f(ks) {
-      var x = 0, y = 0;
-      while (ks.ctor == "Cons") {
-        switch (ks._0) {
-          case left : --x; break;
-          case right: ++x; break;
-          case up   : ++y; break;
-          case down : --y; break;
-        }
-        ks = ks._1;
-      }
-      return { _:{}, x:x, y:y };
-    }
-    return keySignal(f);
-  }
-
-  function is(key) { return keySignal(NList.member(key)); }
-
-  return elm.Native.Keyboard = {
-      isDown:is,
-      directions:F4(dir),
-      keysDown:keysDown,
-      lastPressed:lastKey
-  };
-
-};
-
-Elm.Native.Http = function(elm) {
-  'use strict';
-  elm.Native = elm.Native || {};
-  if (elm.Native.Http) return elm.Native.Http;
-
-
-  var JS = Elm.JavaScript(elm);
-  var List = Elm.List(elm);
-  var Signal = Elm.Signal(elm);
-
-
-  function registerReq(queue,responses) { return function(req) {
-    if (req.url.ctor !== 'Nil') { sendReq(queue,responses,req); }
-   };
-  }
-
-  function updateQueue(queue,responses) {
-    if (queue.length > 0) {
-      elm.notify(responses.id, queue[0].value);
-      if (queue[0].value.ctor !== 'Waiting') {
-        queue.shift();
-        setTimeout(function() { updateQueue(queue,responses); }, 0);
-      }
-    }
-  }
-
-  function setHeader(pair) {
-    request.setRequestHeader( JS.fomString(pair._0), JS.fromString(pair._1) );
-  }
-
-  function sendReq(queue,responses,req) {
-    var response = { value: { ctor:'Waiting' } };
-    queue.push(response);
-
-    var request = null;
-    if (window.ActiveXObject)  { request = new ActiveXObject("Microsoft.XMLHTTP"); }
-    if (window.XMLHttpRequest) { request = new XMLHttpRequest(); }
-    request.onreadystatechange = function(e) {
-      if (request.readyState === 4) {
-        response.value = (request.status >= 200 && request.status < 300 ?
-        { ctor:'Success', _0:JS.toString(request.responseText) } :
-        { ctor:'Failure', _0:request.status, _1:JS.toString(request.statusText) });
-        setTimeout(function() { updateQueue(queue,responses); }, 0);
-      }
-    };
-    request.open(JS.fromString(req.verb), JS.fromString(req.url), true);
-    List.map(setHeader)(req.headers);
-    request.send(JS.fromString(req.body));
-  }
-
-  function send(requests) {
-    var responses = Signal.constant(elm.Http.Waiting);
-    var sender = A2( Signal.lift, registerReq([],responses), requests );
-    function f(x) { return function(y) { return x; } }
-    return A3( Signal.lift2, f, responses, sender );
-  }
-
-  return elm.Native.Http = {send:send};
-
-};
-
-Elm.Native.Graphics.Input = function(elm) {
- "use strict";
-
- elm.Native = elm.Native || {};
- elm.Native.Graphics = elm.Native.Graphics || {};
- if (elm.Native.Graphics.Input) return elm.Native.Graphics.Input;
-
- var Render = ElmRuntime.use(ElmRuntime.Render.Element);
- var newNode = ElmRuntime.use(ElmRuntime.Render.Utils).newElement;
-
- var Signal = Elm.Signal(elm);
- var newElement = Elm.Graphics.Element(elm).newElement;
- var JS = Elm.Native.JavaScript(elm);
- var Tuple2 = Elm.Native.Utils(elm).Tuple2;
-
- function dropDown(values) {
-     var entries = JS.fromList(values);
-     var events = Signal.constant(entries[0]._1);
-
-     var drop = newNode('select');
-     drop.style.border = '0 solid';
-     for (var i = 0; i < entries.length; ++i) {
-         var option = newNode('option');
-         var name = JS.fromString(entries[i]._0);
-         option.value = name;
-         option.innerHTML = name;
-         drop.appendChild(option);
-     }
-     drop.addEventListener('change', function() {
-             elm.notify(events.id, entries[drop.selectedIndex]._1);
-         });
-
-     var t = drop.cloneNode(true);
-     t.style.visibility = "hidden";
-
-     elm.node.appendChild(t);
-     var style = window.getComputedStyle(t, null);
-     var w = Math.ceil(style.getPropertyValue("width").slice(0,-2) - 0);
-     var h = Math.ceil(style.getPropertyValue("height").slice(0,-2) - 0);
-     elm.node.removeChild(t);
-     
-     console.log(w,h);
-     var element = A3(newElement, w, h, {
-             ctor: 'Custom',
-             type: 'DropDown',
-             render: function render(model) { return drop; },
-             update: function update(node, oldModel, newModel) {},
-             model: {}
-         });
-
-     return Tuple2(Signal.constant(element), events);
- }
-
- function buttons(defaultValue) {
-     var events = Signal.constant(defaultValue);
-
-     function render(model) {
-	 var b = newNode('button');
-	 b.style.display = 'block';
-	 b.elmEvent = model.event;
-	 function click() { elm.notify(events.id, b.elmEvent); }
-	 b.addEventListener('click', click);
-	 b.innerHTML = model.text;
-	 return b;
-     }
-
-     function update(node, oldModel, newModel) {
-	 node.elmEvent = newModel.event;
-	 var txt = newModel.text;
-	 if (oldModel.text !== txt) node.innerHTML = txt;
-     }
-
-     function button(evnt, txt) {
-	 return A3(newElement, 100, 40, {
-                     ctor: 'Custom',
-		     type: 'Button',
-		     render: render,
-		     update: update,
-		     model: { event:evnt, text:JS.fromString(txt) }
-	     });
-     }
-
-     return { _:{}, button:F2(button), events:events };
- }
-
- function customButtons(defaultValue) {
-     var events = Signal.constant(defaultValue);
-
-     function render(model) {
-	 var btn = newNode('div');
-	 btn.elmEvent = model.event;
-
-	 btn.elmUp    = Render.render(model.up);
-	 btn.elmHover = Render.render(model.hover);
-	 btn.elmDown  = Render.render(model.down);
-
-	 function replace(node) {
-           if (node !== btn.firstChild) btn.replaceChild(node, btn.firstChild);
-	 }
-	 var overCount = 0;
-	 function over(e) {
-	     if (overCount++ > 0) return;
-	     replace(btn.elmHover);
-	 }
-	 function out(e) {
-	     if (btn.contains(e.toElement || e.relatedTarget)) return;
-	     overCount = 0;
-	     replace(btn.elmUp);
-	 }
-	 function up() {
-	     replace(btn.elmHover);
-	     elm.notify(events.id, btn.elmEvent);
-	 }
-	 function down() { replace(btn.elmDown); }
-	 btn.addEventListener('mouseover', over);
-	 btn.addEventListener('mouseout' , out);
-	 btn.addEventListener('mousedown', down);
-	 btn.addEventListener('mouseup'  , up);
-
-	 btn.appendChild(btn.elmUp);
-	 return btn;
-     }
-
-     function update(node, oldModel, newModel) {
-	 node.elmEvent = newModel.event;
-	 Render.update(node.elmUp, oldModel.up, newModel.up)
-	 Render.update(node.elmHover, oldModel.hover, newModel.hover)
-	 Render.update(node.elmDown, oldModel.down, newModel.down)
-     }
-
-     function button(evnt, up, hover, down) {
-	 return A3(newElement,
-		   Math.max(up.props.width, hover.props.width, down.props.width),
-		   Math.max(up.props.height, hover.props.height, down.props.height),
-                   { ctor: 'Custom',
-		     type: 'CustomButton',
-		     render: render,
-		     update: update,
-		     model: { event:evnt, up:up, hover:hover, down:down }
-		   });
-     }
-
-     return { _:{}, customButton:F4(button), events:events };
- }
-
-
- function checkboxes(defaultValue) {
-     var events = Signal.constant(defaultValue);
-
-     function render(model) {
-	 var b = newNode('input');
-	 b.type = 'checkbox';
-	 b.checked = model.checked;
-	 b.style.display = 'block';
-	 b.elmHandler = model.handler;
-	 function change() { elm.notify(events.id, b.elmHandler(b.checked)); }
-	 b.addEventListener('change', change);
-	 return b;
-     }
-
-     function update(node, oldModel, newModel) {
-	 node.elmHandler = newModel.handler;
-	 node.checked = newModel.checked;
-	 return true;
-     }
-
-     function box(handler, checked) {
-	 return A3(newElement, 13, 13, {
-                     ctor: 'Custom',
-		     type: 'CheckBox',
-		     render: render,
-		     update: update,
-		     model: { checked:checked, handler:handler  }
-	     });
-     }
-
-     return { _:{}, box:F2(box), events:events };
- }
-
- function setRange(node, start, end, dir) {
-     if (node.parentNode) {
-         node.setSelectionRange(start, end, dir);
-     } else {
-         setTimeout(function(){node.setSelectionRange(start, end, dir);}, 0);
-     }
- }
-
- function mkTextPool(type) { return function fields(defaultValue) {
-     var events = Signal.constant(defaultValue);
-
-     var state = null;
-
-     function render(model) {
-	 var field = newNode('input');
-	 field.elmHandler = model.handler;
-
-	 field.id = 'test';
-	 field.type = type;
-	 field.placeholder = JS.fromString(model.placeHolder);
-	 field.value = JS.fromString(model.state.string);
-	 setRange(field, model.state.selectionStart, model.state.selectionEnd, 'forward');
-	 field.style.border = 'none';
-         state = model.state;
-
-	 function update() {
-	     var start = field.selectionStart,
-		 end = field.selectionEnd;
-	     if (field.selectionDirection === 'backward') {
-		 start = end;
-		 end = field.selectionStart;
-	     }
-             state = { _:{},
-                       string:JS.toString(field.value),
-                       selectionStart:start,
-                       selectionEnd:end };
-	     elm.notify(events.id, field.elmHandler(state));
-	 }
-	 function mousedown() {
-	     update();
-	     elm.node.addEventListener('mouseup', mouseup);
-	 }
-	 function mouseup() {
-	     update();
-	     elm.node.removeEventListener('mouseup', mouseup)
-	 }
-	 field.addEventListener('keyup', update);
-	 field.addEventListener('mousedown', mousedown);
-
-	 return field;
-     }
-
-     function update(node, oldModel, newModel) {
-	 node.elmHandler = newModel.handler;
-         if (state === newModel.state) return;
-         var newStr = JS.fromString(newModel.state.string);
-	 if (node.value !== newStr) node.value = newStr;
-
-         var start = newModel.state.selectionStart;
-         var end = newModel.state.selectionEnd;
-         var direction = 'forward';
-         if (end < start) {
-             start = end;
-             end = newModel.state.selectionStart;
-             direction = 'backward';
-         }
- 
-         if (node.selectionStart !== start
-             || node.selectionEnd !== end
-             || node.selectionDirection !== direction) {
-             setRange(node, start, end, direction);
-         }
-     }
-
-     function field(handler, placeHolder, state) {
-	 return A3(newElement, 200, 30,
-                   { ctor: 'Custom',
-		     type: type + 'Input',
-		     render: render,
-		     update: update,
-		     model: { handler:handler,
-			      placeHolder:placeHolder,
-			      state:state }
-		   });
-     }
-
-     return { _:{}, field:F3(field), events:events };
-   }
- }
-
- return elm.Native.Graphics.Input = {
-     buttons:buttons,
-     customButtons:customButtons,
-     checkboxes:checkboxes,
-     fields:mkTextPool('text'),
-     emails:mkTextPool('email'),
-     passwords:mkTextPool('password'),
-     dropDown:dropDown
- };
-
-};
-
-Elm.Native.Graphics.Collage = function(elm) {
- "use strict";
-
- elm.Native = elm.Native || {};
- elm.Native.Graphics = elm.Native.Graphics || {};
- if (elm.Native.Graphics.Collage) return elm.Native.Graphics.Collage;
-
- var newElement = Elm.Graphics.Element(elm).newElement;
- var C = ElmRuntime.use(ElmRuntime.Render.Collage);
-
- function collage(w,h,forms) {
-     return A3(newElement, w, h, {
-                 ctor: 'Custom',
-		 type: 'Collage',
-		 render: C.render,
-		 update: C.update,
-		 model: {w:w, h:h, forms:forms}
-	 });
- }
- return elm.Native.Graphics.Collage = { collage:F3(collage) };
-
-};
-Elm.Window = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var W = Elm.Native.Window(elm);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Window||{};
-  _.$op = {}
-  return elm.Window = _;
-  };
-Elm.WebSocket = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var WS = Elm.Native.WebSocket(elm);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.WebSocket||{};
-  _.$op = {}
-  return elm.WebSocket = _;
-  };
-Elm.Touch = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var T = Elm.Native.Touch(elm);
-  var Touch_0 = F6(function(x_1, y_2, id_3, x0_4, y0_5, t0_6){
-    return {
-      _:{
-      },
-      id:id_3,
-      t0:t0_6,
-      x:x_1,
-      x0:x0_4,
-      y:y_2,
-      y0:y0_5};});
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Touch||{};
-  _.$op = {};
-  _.Touch = Touch_0
-  return elm.Touch = _;
-  };
-Elm.Time = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var T = Elm.Native.Time(elm);
-  var inMilliseconds_4 = function(t_8){
-    return t_8;};
-  var inSeconds_5 = function(t_9){
-    return (t_9/second_1);};
-  var inMinutes_6 = function(t_10){
-    return (t_10/minute_2);};
-  var inHours_7 = function(t_11){
-    return (t_11/hour_3);};
-  var millisecond_0 = 1;
-  var second_1 = (1000*millisecond_0);
-  var minute_2 = (60*second_1);
-  var hour_3 = (60*minute_2);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Time||{};
-  _.$op = {};
-  _.millisecond = millisecond_0;
-  _.second = second_1;
-  _.minute = minute_2;
-  _.hour = hour_3;
-  _.inMilliseconds = inMilliseconds_4;
-  _.inSeconds = inSeconds_5;
-  _.inMinutes = inMinutes_6;
-  _.inHours = inHours_7
-  return elm.Time = _;
-  };
-Elm.Text = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var T = Elm.Native.Text(elm);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Text||{};
-  _.$op = {}
-  return elm.Text = _;
-  };
-Elm.Signal = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var S = Elm.Native.Signal(elm);
-  var L = Elm.List(elm);
-  var combine_0 = A2(L.foldr, S.lift2(function(x_1){
-    return function(y_2){
-      return _L.Cons(x_1,y_2);};}), S.constant(_L.Nil));
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Signal||{};
-  _.$op = {};
-  _.combine = combine_0
-  return elm.Signal = _;
-  };
-Elm.Set = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var Dict = Elm.Dict(elm);
-  var List = Elm.List(elm);
-  var singleton_1 = function(k_13){
-    return A2(Dict.singleton, k_13, {ctor:"Tuple0"});};
-  var insert_2 = function(k_14){
-    return A2(Dict.insert, k_14, {ctor:"Tuple0"});};
-  var fromList_9 = function(xs_15){
-    return A3(List.foldl, insert_2, empty_0, xs_15);};
-  var foldl_10 = F3(function(f_16, b_17, s_18){
-    return A3(Dict.foldl, function(k_19){
-      return function(__20){
-        return function(b_21){
-          return A2(f_16, k_19, b_21);};};}, b_17, s_18);});
-  var foldr_11 = F3(function(f_22, b_23, s_24){
-    return A3(Dict.foldr, function(k_25){
-      return function(__26){
-        return function(b_27){
-          return A2(f_22, k_25, b_27);};};}, b_23, s_24);});
-  var map_12 = F2(function(f_28, s_29){
-    return fromList_9(A2(List.map, f_28, toList_8(s_29)));});
-  var empty_0 = Dict.empty;
-  var remove_3 = Dict.remove;
-  var member_4 = Dict.member;
-  var union_5 = Dict.union;
-  var intersect_6 = Dict.intersect;
-  var diff_7 = Dict.diff;
-  var toList_8 = Dict.keys;
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Set||{};
-  _.$op = {};
-  _.empty = empty_0;
-  _.singleton = singleton_1;
-  _.insert = insert_2;
-  _.remove = remove_3;
-  _.member = member_4;
-  _.union = union_5;
-  _.intersect = intersect_6;
-  _.diff = diff_7;
-  _.toList = toList_8;
-  _.fromList = fromList_9;
-  _.foldl = foldl_10;
-  _.foldr = foldr_11;
-  _.map = map_12
-  return elm.Set = _;
-  };
-Elm.Random = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var R = Elm.Native.Random(elm);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Random||{};
-  _.$op = {}
-  return elm.Random = _;
-  };
-Elm.Prelude = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var N = Elm.Native.Prelude(elm);
-  var LT_5 = {ctor:"LT"};
-  var EQ_6 = {ctor:"EQ"};
-  var GT_7 = {ctor:"GT"};
-  var radians_0 = function(t_9){
-    return t_9;};
-  var degrees_1 = function(d_10){
-    return ((d_10*Math.PI)/180);};
-  var turns_2 = function(r_11){
-    return ((2*Math.PI)*r_11);};
-  var fromPolar_3 = function(_22000_12){
-    return function(){ 
-    switch (_22000_12.ctor) {
-      case 'Tuple2':
-        return {ctor:"Tuple2", _0:(_22000_12._0*N.cos(_22000_12._1)), _1:(_22000_12._0*N.sin(_22000_12._1))};
-    }_E.Case('Line 22, Column 20') }();};
-  var toPolar_4 = function(_27000_15){
-    return function(){ 
-    switch (_27000_15.ctor) {
-      case 'Tuple2':
-        return {ctor:"Tuple2", _0:N.sqrt((Math.pow(_27000_15._0,2)+Math.pow(_27000_15._1,2))), _1:A2(N.atan2, _27000_15._1, _27000_15._0)};
-    }_E.Case('Line 27, Column 18') }();};
-  var otherwise_8 = true;
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Prelude||{};
-  _.$op = {};
-  _.radians = radians_0;
-  _.degrees = degrees_1;
-  _.turns = turns_2;
-  _.fromPolar = fromPolar_3;
-  _.toPolar = toPolar_4;
-  _.LT = LT_5;
-  _.EQ = EQ_6;
-  _.GT = GT_7;
-  _.otherwise = otherwise_8
-  return elm.Prelude = _;
-  };
-Elm.Mouse = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var M = Elm.Native.Mouse(elm);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Mouse||{};
-  _.$op = {}
-  return elm.Mouse = _;
-  };
-Elm.Maybe = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var List = Elm.List(elm);
-  var Just_0 = function(a1){
-    return {ctor:"Just", _0:a1};};
-  var Nothing_1 = {ctor:"Nothing"};
-  var maybe_2 = F3(function(b_7, f_8, m_9){
-    return function(){ 
-    switch (m_9.ctor) {
-      case 'Just':
-        return f_8(m_9._0);
-      case 'Nothing':
-        return b_7;
-    }_E.Case('Line 13, Column 15') }();});
-  var cons_5 = F2(function(mx_12, xs_13){
-    return A3(maybe_2, xs_13, function(x_14){
-      return _L.Cons(x_14,xs_13);}, mx_12);});
-  var isJust_3 = A2(maybe_2, false, function(__11){
-    return true;});
-  var isNothing_4 = function(x){
-    return not(isJust_3(x));};
-  var justs_6 = A2(List.foldr, cons_5, _L.Nil);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Maybe||{};
-  _.$op = {};
-  _.Just = Just_0;
-  _.Nothing = Nothing_1;
-  _.maybe = maybe_2;
-  _.isJust = isJust_3;
-  _.isNothing = isNothing_4;
-  _.cons = cons_5;
-  _.justs = justs_6
-  return elm.Maybe = _;
-  };
-Elm.Matrix2D = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var M = Elm.Native.Matrix2D(elm);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Matrix2D||{};
-  _.$op = {}
-  return elm.Matrix2D = _;
-  };
-Elm.List = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var _ = Elm.Native.Utils(elm); var Native = Native||{};Native.Utils = _;
-  var min = _.min, max = _.max;
-  var L = Elm.Native.List(elm);
-  var concatMap_0 = function(f_8){
-    return function(x){
-      return L.concat(A2(L.map, f_8, x));};};
-  var partition_5 = F2(function(pred_13, lst_14){
-    return function(){ 
-    switch (lst_14.ctor) {
-      case 'Cons':
-        return function(){
-          var _106000_17 = A2(partition_5, pred_13, lst_14._1);
-          var bs_18 = function(){ 
-          switch (_106000_17.ctor) {
-            case 'Tuple2':
-              return _106000_17._0;
-          }_E.Case('Line 106, Column 30') }();
-          var cs_19 = function(){ 
-          switch (_106000_17.ctor) {
-            case 'Tuple2':
-              return _106000_17._1;
-          }_E.Case('Line 106, Column 30') }();
-          return (pred_13(lst_14._0)?{ctor:"Tuple2", _0:_L.Cons(lst_14._0,bs_18), _1:cs_19}:{ctor:"Tuple2", _0:bs_18, _1:_L.Cons(lst_14._0,cs_19)});}();
-      case 'Nil':
-        return {ctor:"Tuple2", _0:_L.Nil, _1:_L.Nil};
-    }_E.Case('Line 104, Column 5') }();});
-  var unzip_6 = function(pairs_24){
-    return function(){ 
-    switch (pairs_24.ctor) {
-      case 'Cons':
-        switch (pairs_24._0.ctor) {
-          case 'Tuple2':
-            return function(){
-              var _127000_28 = unzip_6(pairs_24._1);
-              var xs_29 = function(){ 
-              switch (_127000_28.ctor) {
-                case 'Tuple2':
-                  return _127000_28._0;
-              }_E.Case('Line 127, Column 33') }();
-              var ys_30 = function(){ 
-              switch (_127000_28.ctor) {
-                case 'Tuple2':
-                  return _127000_28._1;
-              }_E.Case('Line 127, Column 33') }();
-              return {ctor:"Tuple2", _0:_L.Cons(pairs_24._0._0,xs_29), _1:_L.Cons(pairs_24._0._1,ys_30)};}();
-        }break;
-      case 'Nil':
-        return {ctor:"Tuple2", _0:_L.Nil, _1:_L.Nil};
-    }_E.Case('Line 125, Column 3') }();};
-  var intersperse_7 = F2(function(sep_35, xs_36){
-    return function(){ 
-    switch (xs_36.ctor) {
-      case 'Cons':
-        switch (xs_36._1.ctor) {
-          case 'Cons':
-            return _L.Cons(xs_36._0,_L.Cons(sep_35,A2(intersperse_7, sep_35, _L.Cons(xs_36._1._0,xs_36._1._1))));
-          case 'Nil':
-            return _L.Cons(xs_36._0,_L.Nil);
-        }break;
-      case 'Nil':
-        return _L.Nil;
-    }_E.Case('Line 145, Column 3') }();});
-  var sum_1 = A2(L.foldl, function(x_9){
-    return function(y_10){
-      return (x_9+y_10);};}, 0);
-  var product_2 = A2(L.foldl, function(x_11){
-    return function(y_12){
-      return (x_11*y_12);};}, 1);
-  var maximum_3 = L.foldl1(max);
-  var minimum_4 = L.foldl1(min);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.List||{};
-  _.$op = {};
-  _.concatMap = concatMap_0;
-  _.sum = sum_1;
-  _.product = product_2;
-  _.maximum = maximum_3;
-  _.minimum = minimum_4;
-  _.partition = partition_5;
-  _.unzip = unzip_6;
-  _.intersperse = intersperse_7
-  return elm.List = _;
-  };
-Elm.Keyboard = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var N = Elm.Native.Keyboard(elm);
-  var arrows_0 = A4(N.directions, 38, 40, 37, 39);
-  var wasd_1 = A4(N.directions, 87, 83, 65, 68);
-  var shift_2 = N.isDown(16);
-  var ctrl_3 = N.isDown(17);
-  var space_4 = N.isDown(32);
-  var enter_5 = N.isDown(13);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Keyboard||{};
-  _.$op = {};
-  _.arrows = arrows_0;
-  _.wasd = wasd_1;
-  _.shift = shift_2;
-  _.ctrl = ctrl_3;
-  _.space = space_4;
-  _.enter = enter_5
-  return elm.Keyboard = _;
-  };
-Elm.Json = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var Dict = Elm.Dict(elm);
-  var JS = Elm.JavaScript(elm);
-  var Native = Elm.Native.Json(elm);
-  var String_0 = function(a1){
-    return {ctor:"String", _0:a1};};
-  var Number_1 = function(a1){
-    return {ctor:"Number", _0:a1};};
-  var Boolean_2 = function(a1){
-    return {ctor:"Boolean", _0:a1};};
-  var Null_3 = {ctor:"Null"};
-  var Array_4 = function(a1){
-    return {ctor:"Array", _0:a1};};
-  var Object_5 = function(a1){
-    return {ctor:"Object", _0:a1};};
-  var toString_6 = F2(function(sep_8, v_9){
-    return JS.toString(A2(Native.toJSString, sep_8, v_9));});
-  var fromString_7 = function(s_10){
-    return Native.fromJSString(JS.fromString(s_10));};
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Json||{};
-  _.$op = {};
-  _.String = String_0;
-  _.Number = Number_1;
-  _.Boolean = Boolean_2;
-  _.Null = Null_3;
-  _.Array = Array_4;
-  _.Object = Object_5;
-  _.toString = toString_6;
-  _.fromString = fromString_7
-  return elm.Json = _;
-  };
-Elm.JavaScript = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.JavaScript||{};
-  _.$op = {}
-  return elm.JavaScript = _;
-  };
-Elm.Http = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var _ = Elm.Native.Http(elm); var Native = Native||{};Native.Http = _;
-  var send = _.send;
-  var _ = Elm.Signal(elm); var Signal = _;
-  var lift = _.lift;
-  var Success_0 = function(a1){
-    return {ctor:"Success", _0:a1};};
-  var Waiting_1 = {ctor:"Waiting"};
-  var Failure_2 = F2(function(a1, a2){
-    return {ctor:"Failure", _0:a1, _1:a2};});
-  var Request_3 = F4(function(verb_8, url_9, body_10, headers_11){
-    return {
-      _:{
-      },
-      body:body_10,
-      headers:headers_11,
-      url:url_9,
-      verb:verb_8};});
-  var get_5 = function(url_12){
-    return A4(Request_3, _str('GET'), url_12, _str(''), _L.Nil);};
-  var post_6 = F2(function(url_13, body_14){
-    return A4(Request_3, _str('POST'), url_13, body_14, _L.Nil);});
-  var sendGet_7 = function(reqs_15){
-    return send(A2(lift, get_5, reqs_15));};
-  var request_4 = Request_3;
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Http||{};
-  _.$op = {};
-  _.Success = Success_0;
-  _.Waiting = Waiting_1;
-  _.Failure = Failure_2;
-  _.Request = Request_3;
-  _.request = request_4;
-  _.get = get_5;
-  _.post = post_6;
-  _.sendGet = sendGet_7
-  return elm.Http = _;
-  };
-Elm.Either = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var _ = Elm.List(elm); var List = _;
-  var Left_0 = function(a1){
-    return {ctor:"Left", _0:a1};};
-  var Right_1 = function(a1){
-    return {ctor:"Right", _0:a1};};
-  var either_2 = F3(function(f_11, g_12, e_13){
-    return function(){ 
-    switch (e_13.ctor) {
-      case 'Left':
-        return f_11(e_13._0);
-      case 'Right':
-        return g_12(e_13._0);
-    }_E.Case('Line 16, Column 16') }();});
-  var isLeft_3 = function(e_16){
-    return function(){ 
-    switch (e_16.ctor) {
-      case 'Left':
-        return true;
-    }
-    return false; }();};
-  var isRight_4 = function(e_17){
-    return function(){ 
-    switch (e_17.ctor) {
-      case 'Right':
-        return true;
-    }
-    return false; }();};
-  var lefts_5 = function(es_18){
-    return A3(List.foldr, consLeft_8, _L.Nil, es_18);};
-  var rights_6 = function(es_19){
-    return A3(List.foldr, consRight_9, _L.Nil, es_19);};
-  var partition_7 = function(es_20){
-    return A3(List.foldr, consEither_10, {ctor:"Tuple2", _0:_L.Nil, _1:_L.Nil}, es_20);};
-  var consLeft_8 = F2(function(e_21, vs_22){
-    return function(){ 
-    switch (e_21.ctor) {
-      case 'Left':
-        return _L.Cons(e_21._0,vs_22);
-      case 'Right':
-        return vs_22;
-    }_E.Case('Line 40, Column 5') }();});
-  var consRight_9 = F2(function(e_24, vs_25){
-    return function(){ 
-    switch (e_24.ctor) {
-      case 'Left':
-        return vs_25;
-      case 'Right':
-        return _L.Cons(e_24._0,vs_25);
-    }_E.Case('Line 45, Column 5') }();});
-  var consEither_10 = F2(function(e_27, _52000_28){
-    return function(){ 
-    switch (_52000_28.ctor) {
-      case 'Tuple2':
-        return function(){ 
-        switch (e_27.ctor) {
-          case 'Left':
-            return {ctor:"Tuple2", _0:_L.Cons(e_27._0,_52000_28._0), _1:_52000_28._1};
-          case 'Right':
-            return {ctor:"Tuple2", _0:_52000_28._0, _1:_L.Cons(e_27._0,_52000_28._1)};
-        }_E.Case('Line 50, Column 5') }();
-    }_E.Case('Line 50, Column 5') }();});
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Either||{};
-  _.$op = {};
-  _.Left = Left_0;
-  _.Right = Right_1;
-  _.either = either_2;
-  _.isLeft = isLeft_3;
-  _.isRight = isRight_4;
-  _.lefts = lefts_5;
-  _.rights = rights_6;
-  _.partition = partition_7;
-  _.consLeft = consLeft_8;
-  _.consRight = consRight_9;
-  _.consEither = consEither_10
-  return elm.Either = _;
-  };
-Elm.Dict = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var Maybe = Elm.Maybe(elm);
-  var Error = Elm.Native.Error(elm);
-  var List = Elm.List(elm);
-  var _ = Elm.Native.Utils(elm); var Native = Native||{};Native.Utils = _;
-  var compare = _.compare;
-  var Red_0 = {ctor:"Red"};
-  var Black_1 = {ctor:"Black"};
-  var RBNode_2 = F5(function(a1, a2, a3, a4, a5){
-    return {ctor:"RBNode", _0:a1, _1:a2, _2:a3, _3:a4, _4:a5};});
-  var RBEmpty_3 = {ctor:"RBEmpty"};
-  var min_5 = function(t_41){
-    return function(){ 
-    switch (t_41.ctor) {
-      case 'RBEmpty':
-        return Error.raise(_str('(min Empty) is not defined'));
-      case 'RBNode':
-        switch (t_41._3.ctor) {
-          case 'RBEmpty':
-            return {ctor:"Tuple2", _0:t_41._1, _1:t_41._2};
-        }
-        return min_5(t_41._3);
-    }_E.Case('Line 104, Column 3') }();};
-  var lookup_6 = F2(function(k_45, t_46){
-    return function(){ 
-    switch (t_46.ctor) {
-      case 'RBEmpty':
-        return Maybe.Nothing;
-      case 'RBNode':
-        return function(){ 
-        var case12 = A2(compare, k_45, t_46._1);
-        switch (case12.ctor) {
-          case 'EQ':
-            return Maybe.Just(t_46._2);
-          case 'GT':
-            return A2(lookup_6, k_45, t_46._4);
-          case 'LT':
-            return A2(lookup_6, k_45, t_46._3);
-        }_E.Case('Line 124, Column 5') }();
-    }_E.Case('Line 121, Column 2') }();});
-  var findWithDefault_7 = F3(function(base_51, k_52, t_53){
-    return function(){ 
-    switch (t_53.ctor) {
-      case 'RBEmpty':
-        return base_51;
-      case 'RBNode':
-        return function(){ 
-        var case19 = A2(compare, k_52, t_53._1);
-        switch (case19.ctor) {
-          case 'EQ':
-            return t_53._2;
-          case 'GT':
-            return A3(findWithDefault_7, base_51, k_52, t_53._4);
-          case 'LT':
-            return A3(findWithDefault_7, base_51, k_52, t_53._3);
-        }_E.Case('Line 136, Column 5') }();
-    }_E.Case('Line 133, Column 2') }();});
-  var member_8 = F2(function(k_58, t_59){
-    return Maybe.isJust(A2(lookup_6, k_58, t_59));});
-  var rotateLeft_9 = function(t_60){
-    return function(){ 
-    switch (t_60.ctor) {
-      case 'RBNode':
-        switch (t_60._4.ctor) {
-          case 'RBNode':
-            return A5(RBNode_2, t_60._0, t_60._4._1, t_60._4._2, A5(RBNode_2, Red_0, t_60._1, t_60._2, t_60._3, t_60._4._3), t_60._4._4);
-        }break;
-    }
-    return Error.raise(_str('rotateLeft of a node without enough children')); }();};
-  var rotateRight_10 = function(t_70){
-    return function(){ 
-    switch (t_70.ctor) {
-      case 'RBNode':
-        switch (t_70._3.ctor) {
-          case 'RBNode':
-            return A5(RBNode_2, t_70._0, t_70._3._1, t_70._3._2, t_70._3._3, A5(RBNode_2, Red_0, t_70._1, t_70._2, t_70._3._4, t_70._4));
-        }break;
-    }
-    return Error.raise(_str('rotateRight of a node without enough children')); }();};
-  var rotateLeftIfNeeded_11 = function(t_80){
-    return function(){ 
-    switch (t_80.ctor) {
-      case 'RBNode':
-        switch (t_80._4.ctor) {
-          case 'RBNode':
-            switch (t_80._4._0.ctor) {
-              case 'Red':
-                return rotateLeft_9(t_80);
-            }break;
-        }break;
-    }
-    return t_80; }();};
-  var rotateRightIfNeeded_12 = function(t_81){
-    return function(){ 
-    switch (t_81.ctor) {
-      case 'RBNode':
-        switch (t_81._3.ctor) {
-          case 'RBNode':
-            switch (t_81._3._0.ctor) {
-              case 'Red':
-                switch (t_81._3._3.ctor) {
-                  case 'RBNode':
-                    switch (t_81._3._3._0.ctor) {
-                      case 'Red':
-                        return rotateRight_10(t_81);
-                    }break;
-                }break;
-            }break;
-        }break;
-    }
-    return t_81; }();};
-  var otherColor_13 = function(c_82){
-    return function(){ 
-    switch (c_82.ctor) {
-      case 'Black':
-        return Red_0;
-      case 'Red':
-        return Black_1;
-    }_E.Case('Line 185, Column 16') }();};
-  var color_flip_14 = function(t_83){
-    return function(){ 
-    switch (t_83.ctor) {
-      case 'RBNode':
-        switch (t_83._3.ctor) {
-          case 'RBNode':
-            switch (t_83._4.ctor) {
-              case 'RBNode':
-                return A5(RBNode_2, otherColor_13(t_83._0), t_83._1, t_83._2, A5(RBNode_2, otherColor_13(t_83._3._0), t_83._3._1, t_83._3._2, t_83._3._3, t_83._3._4), A5(RBNode_2, otherColor_13(t_83._4._0), t_83._4._1, t_83._4._2, t_83._4._3, t_83._4._4));
-            }break;
-        }break;
-    }
-    return Error.raise(_str('color_flip called on a Empty or Node with a Empty child')); }();};
-  var color_flipIfNeeded_15 = function(t_97){
-    return function(){ 
-    switch (t_97.ctor) {
-      case 'RBNode':
-        switch (t_97._3.ctor) {
-          case 'RBNode':
-            switch (t_97._3._0.ctor) {
-              case 'Red':
-                switch (t_97._4.ctor) {
-                  case 'RBNode':
-                    switch (t_97._4._0.ctor) {
-                      case 'Red':
-                        return color_flip_14(t_97);
-                    }break;
-                }break;
-            }break;
-        }break;
-    }
-    return t_97; }();};
-  var fixUp_16 = function(t_98){
-    return color_flipIfNeeded_15(rotateRightIfNeeded_12(rotateLeftIfNeeded_11(t_98)));};
-  var ensureBlackRoot_17 = function(t_99){
-    return function(){ 
-    switch (t_99.ctor) {
-      case 'RBNode':
-        switch (t_99._0.ctor) {
-          case 'Red':
-            return A5(RBNode_2, Black_1, t_99._1, t_99._2, t_99._3, t_99._4);
-        }break;
-    }
-    return t_99; }();};
-  var insert_18 = F3(function(k_104, v_105, t_106){
-    return function(){
-      var ins_107 = function(t_108){
-        return function(){ 
-        switch (t_108.ctor) {
-          case 'RBEmpty':
-            return A5(RBNode_2, Red_0, k_104, v_105, RBEmpty_3, RBEmpty_3);
-          case 'RBNode':
-            return function(){
-              var h_114 = function(){ 
-              var case114 = A2(compare, k_104, t_108._1);
-              switch (case114.ctor) {
-                case 'EQ':
-                  return A5(RBNode_2, t_108._0, t_108._1, v_105, t_108._3, t_108._4);
-                case 'GT':
-                  return A5(RBNode_2, t_108._0, t_108._1, t_108._2, t_108._3, ins_107(t_108._4));
-                case 'LT':
-                  return A5(RBNode_2, t_108._0, t_108._1, t_108._2, ins_107(t_108._3), t_108._4);
-              }_E.Case('Line 218, Column 19') }();
-              return fixUp_16(h_114);}();
-        }_E.Case('Line 215, Column 7') }();};
-      return ensureBlackRoot_17(ins_107(t_106));}();});
-  var singleton_19 = F2(function(k_115, v_116){
-    return A3(insert_18, k_115, v_116, RBEmpty_3);});
-  var isRed_20 = function(t_117){
-    return function(){ 
-    switch (t_117.ctor) {
-      case 'RBNode':
-        switch (t_117._0.ctor) {
-          case 'Red':
-            return true;
-        }break;
-    }
-    return false; }();};
-  var isRedLeft_21 = function(t_118){
-    return function(){ 
-    switch (t_118.ctor) {
-      case 'RBNode':
-        switch (t_118._3.ctor) {
-          case 'RBNode':
-            switch (t_118._3._0.ctor) {
-              case 'Red':
-                return true;
-            }break;
-        }break;
-    }
-    return false; }();};
-  var isRedLeftLeft_22 = function(t_119){
-    return function(){ 
-    switch (t_119.ctor) {
-      case 'RBNode':
-        switch (t_119._3.ctor) {
-          case 'RBNode':
-            switch (t_119._3._3.ctor) {
-              case 'RBNode':
-                switch (t_119._3._3._0.ctor) {
-                  case 'Red':
-                    return true;
-                }break;
-            }break;
-        }break;
-    }
-    return false; }();};
-  var isRedRight_23 = function(t_120){
-    return function(){ 
-    switch (t_120.ctor) {
-      case 'RBNode':
-        switch (t_120._4.ctor) {
-          case 'RBNode':
-            switch (t_120._4._0.ctor) {
-              case 'Red':
-                return true;
-            }break;
-        }break;
-    }
-    return false; }();};
-  var isRedRightLeft_24 = function(t_121){
-    return function(){ 
-    switch (t_121.ctor) {
-      case 'RBNode':
-        switch (t_121._4.ctor) {
-          case 'RBNode':
-            switch (t_121._4._3.ctor) {
-              case 'RBNode':
-                switch (t_121._4._3._0.ctor) {
-                  case 'Red':
-                    return true;
-                }break;
-            }break;
-        }break;
-    }
-    return false; }();};
-  var moveRedLeft_25 = function(t_122){
-    return function(){
-      var t$_123 = color_flip_14(t_122);
-      return function(){ 
-      switch (t$_123.ctor) {
-        case 'RBNode':
-          return function(){ 
-          switch (t$_123._4.ctor) {
-            case 'RBNode':
-              switch (t$_123._4._3.ctor) {
-                case 'RBNode':
-                  switch (t$_123._4._3._0.ctor) {
-                    case 'Red':
-                      return color_flip_14(rotateLeft_9(A5(RBNode_2, t$_123._0, t$_123._1, t$_123._2, t$_123._3, rotateRight_10(t$_123._4))));
-                  }break;
-              }break;
-          }
-          return t$_123; }();
-      }
-      return t$_123; }();}();};
-  var moveRedRight_26 = function(t_129){
-    return function(){
-      var t$_130 = color_flip_14(t_129);
-      return (isRedLeftLeft_22(t$_130)?color_flip_14(rotateRight_10(t$_130)):t$_130);}();};
-  var moveRedLeftIfNeeded_27 = function(t_131){
-    return ((isRedLeft_21(t_131)||isRedLeftLeft_22(t_131))?t_131:moveRedLeft_25(t_131));};
-  var moveRedRightIfNeeded_28 = function(t_132){
-    return ((isRedRight_23(t_132)||isRedRightLeft_24(t_132))?t_132:moveRedRight_26(t_132));};
-  var deleteMin_29 = function(t_133){
-    return function(){
-      var del_134 = function(t_135){
-        return function(){ 
-        switch (t_135.ctor) {
-          case 'RBNode':
-            switch (t_135._3.ctor) {
-              case 'RBEmpty':
-                return RBEmpty_3;
-            }break;
-        }
-        return function(){ 
-        var case198 = moveRedLeftIfNeeded_27(t_135);
-        switch (case198.ctor) {
-          case 'RBEmpty':
-            return RBEmpty_3;
-          case 'RBNode':
-            return fixUp_16(A5(RBNode_2, case198._0, case198._1, case198._2, del_134(case198._3), case198._4));
-        }_E.Case('Line 296, Column 12') }(); }();};
-      return ensureBlackRoot_17(del_134(t_133));}();};
-  var remove_30 = F2(function(k_141, t_142){
-    return function(){
-      var eq_and_noRightNode_143 = function(t_149){
-        return function(){ 
-        switch (t_149.ctor) {
-          case 'RBNode':
-            switch (t_149._4.ctor) {
-              case 'RBEmpty':
-                return _N.eq(k_141,t_149._1);
-            }break;
-        }
-        return false; }();};
-      var eq_144 = function(t_151){
-        return function(){ 
-        switch (t_151.ctor) {
-          case 'RBNode':
-            return _N.eq(k_141,t_151._1);
-        }
-        return false; }();};
-      var delLT_145 = function(t_153){
-        return function(){ 
-        var case216 = moveRedLeftIfNeeded_27(t_153);
-        switch (case216.ctor) {
-          case 'RBEmpty':
-            return Error.raise(_str('delLT on Empty'));
-          case 'RBNode':
-            return fixUp_16(A5(RBNode_2, case216._0, case216._1, case216._2, del_148(case216._3), case216._4));
-        }_E.Case('Line 321, Column 17') }();};
-      var delEQ_146 = function(t_159){
-        return function(){ 
-        switch (t_159.ctor) {
-          case 'RBEmpty':
-            return Error.raise(_str('delEQ called on a Empty'));
-          case 'RBNode':
-            return function(){
-              var _325000_163 = min_5(t_159._4);
-              var k$_164 = function(){ 
-              switch (_325000_163.ctor) {
-                case 'Tuple2':
-                  return _325000_163._0;
-              }_E.Case('Line 325, Column 53') }();
-              var v$_165 = function(){ 
-              switch (_325000_163.ctor) {
-                case 'Tuple2':
-                  return _325000_163._1;
-              }_E.Case('Line 325, Column 53') }();
-              return fixUp_16(A5(RBNode_2, t_159._0, k$_164, v$_165, t_159._3, deleteMin_29(t_159._4)));}();
-        }_E.Case('Line 324, Column 17') }();};
-      var delGT_147 = function(t_170){
-        return function(){ 
-        switch (t_170.ctor) {
-          case 'RBEmpty':
-            return Error.raise(_str('delGT called on a Empty'));
-          case 'RBNode':
-            return fixUp_16(A5(RBNode_2, t_170._0, t_170._1, t_170._2, t_170._3, del_148(t_170._4)));
-        }_E.Case('Line 328, Column 17') }();};
-      var del_148 = function(t_176){
-        return function(){ 
-        switch (t_176.ctor) {
-          case 'RBEmpty':
-            return RBEmpty_3;
-          case 'RBNode':
-            return ((_N.cmp(k_141,t_176._1).ctor==='LT')?delLT_145(t_176):function(){
-              var u_178 = (isRedLeft_21(t_176)?rotateRight_10(t_176):t_176);
-              return (eq_and_noRightNode_143(u_178)?RBEmpty_3:function(){
-                var t$_179 = moveRedRightIfNeeded_28(t_176);
-                return (eq_144(t$_179)?delEQ_146(t$_179):delGT_147(t$_179));}());}());
-        }_E.Case('Line 331, Column 15') }();};
-      return (A2(member_8, k_141, t_142)?ensureBlackRoot_17(del_148(t_142)):t_142);}();});
-  var map_31 = F2(function(f_180, t_181){
-    return function(){ 
-    switch (t_181.ctor) {
-      case 'RBEmpty':
-        return RBEmpty_3;
-      case 'RBNode':
-        return A5(RBNode_2, t_181._0, t_181._1, f_180(t_181._2), A2(map_31, f_180, t_181._3), A2(map_31, f_180, t_181._4));
-    }_E.Case('Line 351, Column 3') }();});
-  var foldl_32 = F3(function(f_187, acc_188, t_189){
-    return function(){ 
-    switch (t_189.ctor) {
-      case 'RBEmpty':
-        return acc_188;
-      case 'RBNode':
-        return A3(foldl_32, f_187, A3(f_187, t_189._1, t_189._2, A3(foldl_32, f_187, acc_188, t_189._3)), t_189._4);
-    }_E.Case('Line 359, Column 3') }();});
-  var foldr_33 = F3(function(f_194, acc_195, t_196){
-    return function(){ 
-    switch (t_196.ctor) {
-      case 'RBEmpty':
-        return acc_195;
-      case 'RBNode':
-        return A3(foldr_33, f_194, A3(f_194, t_196._1, t_196._2, A3(foldr_33, f_194, acc_195, t_196._4)), t_196._3);
-    }_E.Case('Line 367, Column 3') }();});
-  var union_34 = F2(function(t1_201, t2_202){
-    return A3(foldl_32, insert_18, t2_202, t1_201);});
-  var intersect_35 = F2(function(t1_203, t2_204){
-    return function(){
-      var combine_205 = F3(function(k_206, v_207, t_208){
-        return (A2(member_8, k_206, t2_204)?A3(insert_18, k_206, v_207, t_208):t_208);});
-      return A3(foldl_32, combine_205, empty_4, t1_203);}();});
-  var diff_36 = F2(function(t1_209, t2_210){
-    return A3(foldl_32, function(k_211){
-      return function(v_212){
-        return function(t_213){
-          return A2(remove_30, k_211, t_213);};};}, t1_209, t2_210);});
-  var keys_37 = function(t_214){
-    return A3(foldr_33, function(k_215){
-      return function(v_216){
-        return function(acc_217){
-          return _L.Cons(k_215,acc_217);};};}, _L.Nil, t_214);};
-  var values_38 = function(t_218){
-    return A3(foldr_33, function(k_219){
-      return function(v_220){
-        return function(acc_221){
-          return _L.Cons(v_220,acc_221);};};}, _L.Nil, t_218);};
-  var toList_39 = function(t_222){
-    return A3(foldr_33, function(k_223){
-      return function(v_224){
-        return function(acc_225){
-          return _L.Cons({ctor:"Tuple2", _0:k_223, _1:v_224},acc_225);};};}, _L.Nil, t_222);};
-  var fromList_40 = function(assocs_226){
-    return A3(List.foldl, function(_0_227){
-      return function(){ 
-      switch (_0_227.ctor) {
-        case 'Tuple2':
-          return function(d_230){
-            return A3(insert_18, _0_227._0, _0_227._1, d_230);};
-      }_E.Case('Line 402, Column 43') }();}, empty_4, assocs_226);};
-  var empty_4 = RBEmpty_3;
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Dict||{};
-  _.$op = {};
-  _.empty = empty_4;
-  _.lookup = lookup_6;
-  _.findWithDefault = findWithDefault_7;
-  _.member = member_8;
-  _.insert = insert_18;
-  _.singleton = singleton_19;
-  _.remove = remove_30;
-  _.map = map_31;
-  _.foldl = foldl_32;
-  _.foldr = foldr_33;
-  _.union = union_34;
-  _.intersect = intersect_35;
-  _.diff = diff_36;
-  _.keys = keys_37;
-  _.values = values_38;
-  _.toList = toList_39;
-  _.fromList = fromList_40
-  return elm.Dict = _;
-  };
-Elm.Date = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var Mon_0 = {ctor:"Mon"};
-  var Tue_1 = {ctor:"Tue"};
-  var Wed_2 = {ctor:"Wed"};
-  var Thu_3 = {ctor:"Thu"};
-  var Fri_4 = {ctor:"Fri"};
-  var Sat_5 = {ctor:"Sat"};
-  var Sun_6 = {ctor:"Sun"};
-  var Jan_7 = {ctor:"Jan"};
-  var Feb_8 = {ctor:"Feb"};
-  var Mar_9 = {ctor:"Mar"};
-  var Apr_10 = {ctor:"Apr"};
-  var May_11 = {ctor:"May"};
-  var Jun_12 = {ctor:"Jun"};
-  var Jul_13 = {ctor:"Jul"};
-  var Aug_14 = {ctor:"Aug"};
-  var Sep_15 = {ctor:"Sep"};
-  var Oct_16 = {ctor:"Oct"};
-  var Nov_17 = {ctor:"Nov"};
-  var Dec_18 = {ctor:"Dec"};
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Date||{};
-  _.$op = {};
-  _.Mon = Mon_0;
-  _.Tue = Tue_1;
-  _.Wed = Wed_2;
-  _.Thu = Thu_3;
-  _.Fri = Fri_4;
-  _.Sat = Sat_5;
-  _.Sun = Sun_6;
-  _.Jan = Jan_7;
-  _.Feb = Feb_8;
-  _.Mar = Mar_9;
-  _.Apr = Apr_10;
-  _.May = May_11;
-  _.Jun = Jun_12;
-  _.Jul = Jul_13;
-  _.Aug = Aug_14;
-  _.Sep = Sep_15;
-  _.Oct = Oct_16;
-  _.Nov = Nov_17;
-  _.Dec = Dec_18
-  return elm.Date = _;
-  };
-Elm.Color = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var Color_0 = F4(function(a1, a2, a3, a4){
-    return {ctor:"Color", _0:a1, _1:a2, _2:a3, _3:a4};});
-  var Linear_20 = F3(function(a1, a2, a3){
-    return {ctor:"Linear", _0:a1, _1:a2, _2:a3};});
-  var Radial_21 = F5(function(a1, a2, a3, a4, a5){
-    return {ctor:"Radial", _0:a1, _1:a2, _2:a3, _3:a4, _4:a5};});
-  var rgb_2 = F3(function(r_24, g_25, b_26){
-    return A4(Color_0, r_24, g_25, b_26, 1);});
-  var rgba_1 = Color_0;
-  var red_3 = A4(Color_0, 255, 0, 0, 1);
-  var lime_4 = A4(Color_0, 0, 255, 0, 1);
-  var blue_5 = A4(Color_0, 0, 0, 255, 1);
-  var yellow_6 = A4(Color_0, 255, 255, 0, 1);
-  var cyan_7 = A4(Color_0, 0, 255, 255, 1);
-  var magenta_8 = A4(Color_0, 255, 0, 255, 1);
-  var black_9 = A4(Color_0, 0, 0, 0, 1);
-  var white_10 = A4(Color_0, 255, 255, 255, 1);
-  var gray_11 = A4(Color_0, 128, 128, 128, 1);
-  var grey_12 = A4(Color_0, 128, 128, 128, 1);
-  var maroon_13 = A4(Color_0, 128, 0, 0, 1);
-  var navy_14 = A4(Color_0, 0, 0, 128, 1);
-  var green_15 = A4(Color_0, 0, 128, 0, 1);
-  var teal_16 = A4(Color_0, 0, 128, 128, 1);
-  var purple_17 = A4(Color_0, 128, 0, 128, 1);
-  var violet_18 = A4(Color_0, 238, 130, 238, 1);
-  var forestGreen_19 = A4(Color_0, 34, 139, 34, 1);
-  var linear_22 = Linear_20;
-  var radial_23 = Radial_21;
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Color||{};
-  _.$op = {};
-  _.Color = Color_0;
-  _.rgba = rgba_1;
-  _.rgb = rgb_2;
-  _.red = red_3;
-  _.lime = lime_4;
-  _.blue = blue_5;
-  _.yellow = yellow_6;
-  _.cyan = cyan_7;
-  _.magenta = magenta_8;
-  _.black = black_9;
-  _.white = white_10;
-  _.gray = gray_11;
-  _.grey = grey_12;
-  _.maroon = maroon_13;
-  _.navy = navy_14;
-  _.green = green_15;
-  _.teal = teal_16;
-  _.purple = purple_17;
-  _.violet = violet_18;
-  _.forestGreen = forestGreen_19;
-  _.Linear = Linear_20;
-  _.Radial = Radial_21;
-  _.linear = linear_22;
-  _.radial = radial_23
-  return elm.Color = _;
-  };
-Elm.Char = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var N = Elm.Native.Char(elm);
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Char||{};
-  _.$op = {}
-  return elm.Char = _;
-  };
-Elm.Automaton = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var _ = Elm.Signal(elm); var Signal = _;
-  var lift = _.lift, foldp = _.foldp;
-  var Step_0 = function(a1){
-    return {ctor:"Step", _0:a1};};
-  var run_1 = F3(function(auto_12, base_13, inputs_14){
-    return function(){
-      var step_15 = F2(function(a_16, _15000_17){
-        return function(){ 
-        switch (_15000_17.ctor) {
-          case 'Tuple2':
-            switch (_15000_17._0.ctor) {
-              case 'Step':
-                return _15000_17._0._0(a_16);
-            }break;
-        }_E.Case('Line 15, Column 28') }();});
-      return A2(lift, function(_0_19){
-        return function(){ 
-        switch (_0_19.ctor) {
-          case 'Tuple2':
-            return _0_19._1;
-        }_E.Case('Line 16, Column 23') }();}, A3(foldp, step_15, {ctor:"Tuple2", _0:auto_12, _1:base_13}, inputs_14));}();});
-  var step_2 = F2(function(a_22, _20000_23){
-    return function(){ 
-    switch (_20000_23.ctor) {
-      case 'Step':
-        return _20000_23._0(a_22);
-    }_E.Case('Line 20, Column 19') }();});
-  $op['>>>'] = F2(function(f_25, g_26){
-    return Step_0(function(a_27){
-      return function(){
-        var _25000_28 = A2(step_2, a_27, f_25);
-        var f$_29 = function(){ 
-        switch (_25000_28.ctor) {
-          case 'Tuple2':
-            return _25000_28._0;
-        }_E.Case('Line 25, Column 29') }();
-        var b_30 = function(){ 
-        switch (_25000_28.ctor) {
-          case 'Tuple2':
-            return _25000_28._1;
-        }_E.Case('Line 25, Column 29') }();
-        var _26000_31 = A2(step_2, b_30, g_26);
-        var g$_32 = function(){ 
-        switch (_26000_31.ctor) {
-          case 'Tuple2':
-            return _26000_31._0;
-        }_E.Case('Line 26, Column 29') }();
-        var c_33 = function(){ 
-        switch (_26000_31.ctor) {
-          case 'Tuple2':
-            return _26000_31._1;
-        }_E.Case('Line 26, Column 29') }();
-        return {ctor:"Tuple2", _0:$op['>>>'](f$_29)(g$_32), _1:c_33};}();});});
-  $op['<<<'] = F2(function(g_42, f_43){
-    return $op['>>>'](f_43)(g_42);});
-  var combine_3 = function(autos_44){
-    return Step_0(function(a_45){
-      return function(){
-        var _36000_46 = unzip(A2(map, step_2(a_45), autos_44));
-        var autos$_47 = function(){ 
-        switch (_36000_46.ctor) {
-          case 'Tuple2':
-            return _36000_46._0;
-        }_E.Case('Line 36, Column 34') }();
-        var bs_48 = function(){ 
-        switch (_36000_46.ctor) {
-          case 'Tuple2':
-            return _36000_46._1;
-        }_E.Case('Line 36, Column 34') }();
-        return {ctor:"Tuple2", _0:combine_3(autos$_47), _1:bs_48};}();});};
-  var pure_4 = function(f_53){
-    return Step_0(function(x_54){
-      return {ctor:"Tuple2", _0:pure_4(f_53), _1:f_53(x_54)};});};
-  var state_5 = F2(function(s_55, f_56){
-    return Step_0(function(x_57){
-      return function(){
-        var s$_58 = A2(f_56, x_57, s_55);
-        return {ctor:"Tuple2", _0:A2(state_5, s$_58, f_56), _1:s$_58};}();});});
-  var hiddenState_6 = F2(function(s_59, f_60){
-    return Step_0(function(x_61){
-      return function(){
-        var _60000_62 = A2(f_60, x_61, s_59);
-        var s$_63 = function(){ 
-        switch (_60000_62.ctor) {
-          case 'Tuple2':
-            return _60000_62._0;
-        }_E.Case('Line 60, Column 46') }();
-        var out_64 = function(){ 
-        switch (_60000_62.ctor) {
-          case 'Tuple2':
-            return _60000_62._1;
-        }_E.Case('Line 60, Column 46') }();
-        return {ctor:"Tuple2", _0:A2(hiddenState_6, s$_63, f_60), _1:out_64};}();});});
-  var enqueue_9 = F2(function(x_71, _69000_72){
-    return function(){ 
-    switch (_69000_72.ctor) {
-      case 'Tuple2':
-        return {ctor:"Tuple2", _0:_L.Cons(x_71,_69000_72._0), _1:_69000_72._1};
-    }_E.Case('Line 69, Column 22') }();});
-  var dequeue_10 = function(q_75){
-    return function(){ 
-    switch (q_75.ctor) {
-      case 'Tuple2':
-        switch (q_75._0.ctor) {
-          case 'Nil':
-            switch (q_75._1.ctor) {
-              case 'Nil':
-                return Nothing;
-            }break;
-        }
-        switch (q_75._1.ctor) {
-          case 'Cons':
-            return Just({ctor:"Tuple2", _0:q_75._1._0, _1:{ctor:"Tuple2", _0:q_75._0, _1:q_75._1._1}});
-          case 'Nil':
-            return enqueue_9({ctor:"Tuple2", _0:_L.Nil, _1:reverse(q_75._0)});
-        }break;
-    }_E.Case('Line 70, Column 13') }();};
-  var average_11 = function(k_80){
-    return function(){
-      var step_81 = F2(function(n_83, _80000_84){
-        return function(){ 
-        switch (_80000_84.ctor) {
-          case 'Tuple3':
-            return (_N.eq(_80000_84._1,k_80)?A2(stepFull_82, n_83, {ctor:"Tuple3", _0:_80000_84._0, _1:_80000_84._1, _2:_80000_84._2}):{ctor:"Tuple2", _0:{ctor:"Tuple3", _0:A2(enqueue_9, n_83, _80000_84._0), _1:(1+_80000_84._1), _2:(_80000_84._2+n_83)}, _1:((_80000_84._2+n_83)/(1+_80000_84._1))});
-        }_E.Case('Line 79, Column 11') }();});
-      var stepFull_82 = F2(function(n_88, _86000_89){
-        return function(){ 
-        switch (_86000_89.ctor) {
-          case 'Tuple3':
-            return function(){ 
-            var case49 = dequeue_10(_86000_89._0);
-            switch (case49.ctor) {
-              case 'Just':
-                switch (case49._0.ctor) {
-                  case 'Tuple2':
-                    return function(){
-                      var sum$_95 = ((_86000_89._2+n_88)-case49._0._0);
-                      return {ctor:"Tuple2", _0:{ctor:"Tuple3", _0:A2(enqueue_9, n_88, case49._0._1), _1:_86000_89._1, _2:sum$_95}, _1:(sum$_95/_86000_89._1)};}();
-                }break;
-              case 'Nothing':
-                return {ctor:"Tuple2", _0:{ctor:"Tuple3", _0:_86000_89._0, _1:_86000_89._1, _2:_86000_89._2}, _1:0};
-            }_E.Case('Line 82, Column 11') }();
-        }_E.Case('Line 82, Column 11') }();});
-      return A2(hiddenState_6, {ctor:"Tuple3", _0:empty_8, _1:0, _2:0}, step_81);}();};
-  var count_7 = A2(state_5, 0, function(__69){
-    return function(c_70){
-      return (1+c_70);};});
-  var empty_8 = {ctor:"Tuple2", _0:_L.Nil, _1:_L.Nil};
-  elm.Native = elm.Native||{};
-  var _ = elm.Native.Automaton||{};
-  _.$op = {'>>>' : $op['>>>'], '<<<' : $op['<<<']};
-  _.Step = Step_0;
-  _.run = run_1;
-  _.step = step_2;
-  _.combine = combine_3;
-  _.pure = pure_4;
-  _.state = state_5;
-  _.hiddenState = hiddenState_6;
-  _.count = count_7;
-  _.empty = empty_8;
-  _.enqueue = enqueue_9;
-  _.dequeue = dequeue_10;
-  _.average = average_11
-  return elm.Automaton = _;
-  };
-Elm.JavaScript = Elm.JavaScript||{};
-Elm.JavaScript.Experimental = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var JS = Elm.JavaScript(elm);
-  var toRecord_0 = JS.toRecord;
-  var fromRecord_1 = JS.fromRecord;
-  elm.Native = elm.Native||{};
-  elm.Native.JavaScript = elm.Native.JavaScript||{};
-  var _ = elm.Native.JavaScript.Experimental||{};
-  _.$op = {};
-  _.toRecord = toRecord_0;
-  _.fromRecord = fromRecord_1
-  elm.JavaScript = elm.JavaScript||{};
-  return elm.JavaScript.Experimental = _;
-  };
-Elm.Graphics = Elm.Graphics||{};
-Elm.Graphics.Input = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var _ = Elm.Signal(elm); var Signal = _;
-  var lift = _.lift, dropRepeats = _.dropRepeats;
-  var N = Elm.Native.Graphics.Input(elm);
-  var _ = Elm.List(elm); var List = _;
-  var id_0 = function(x_10){
-    return x_10;};
-  var button_1 = function(txt_11){
-    return function(){
-      var pool_12 = N.buttons({ctor:"Tuple0"});
-      return {ctor:"Tuple2", _0:A2(pool_12.button, {ctor:"Tuple0"}, txt_11), _1:pool_12.events};}();};
-  var customButton_2 = F3(function(up_13, hover_14, down_15){
-    return function(){
-      var pool_16 = N.customButtons({ctor:"Tuple0"});
-      return {ctor:"Tuple2", _0:A4(pool_16.customButton, {ctor:"Tuple0"}, up_13, hover_14, down_15), _1:pool_16.events};}();});
-  var checkbox_3 = function(b_17){
-    return function(){
-      var cbs_18 = N.checkboxes(b_17);
-      return {ctor:"Tuple2", _0:A2(lift, cbs_18.box(id_0), cbs_18.events), _1:cbs_18.events};}();};
-  var FieldState_4 = F3(function(string_19, selectionStart_20, selectionEnd_21){
-    return {
-      _:{
-      },
-      selectionEnd:selectionEnd_21,
-      selectionStart:selectionStart_20,
-      string:string_19};});
-  var field_6 = function(placeHolder_22){
-    return function(){
-      var tfs_23 = N.fields(emptyFieldState_5);
-      var changes_24 = dropRepeats(tfs_23.events);
-      return {ctor:"Tuple2", _0:A2(lift, A2(tfs_23.field, id_0, placeHolder_22), changes_24), _1:dropRepeats(A2(lift, function(__25){
-        return __25.string;}, changes_24))};}();};
-  var password_7 = function(placeHolder_26){
-    return function(){
-      var tfs_27 = N.passwords(emptyFieldState_5);
-      var changes_28 = dropRepeats(tfs_27.events);
-      return {ctor:"Tuple2", _0:A2(lift, A2(tfs_27.field, id_0, placeHolder_26), changes_28), _1:dropRepeats(A2(lift, function(__29){
-        return __29.string;}, changes_28))};}();};
-  var email_8 = function(placeHolder_30){
-    return function(){
-      var tfs_31 = N.emails(emptyFieldState_5);
-      var changes_32 = dropRepeats(tfs_31.events);
-      return {ctor:"Tuple2", _0:A2(lift, A2(tfs_31.field, id_0, placeHolder_30), changes_32), _1:dropRepeats(A2(lift, function(__33){
-        return __33.string;}, changes_32))};}();};
-  var stringDropDown_9 = function(strs_34){
-    return N.dropDown(A2(List.map, function(s_35){
-      return {ctor:"Tuple2", _0:s_35, _1:s_35};}, strs_34));};
-  var emptyFieldState_5 = {
-    _:{
-    },
-    selectionEnd:0,
-    selectionStart:0,
-    string:_str('')};
-  elm.Native = elm.Native||{};
-  elm.Native.Graphics = elm.Native.Graphics||{};
-  var _ = elm.Native.Graphics.Input||{};
-  _.$op = {};
-  _.id = id_0;
-  _.button = button_1;
-  _.customButton = customButton_2;
-  _.checkbox = checkbox_3;
-  _.FieldState = FieldState_4;
-  _.emptyFieldState = emptyFieldState_5;
-  _.field = field_6;
-  _.password = password_7;
-  _.email = email_8;
-  _.stringDropDown = stringDropDown_9
-  elm.Graphics = elm.Graphics||{};
-  return elm.Graphics.Input = _;
-  };
-Elm.Graphics = Elm.Graphics||{};
-Elm.Graphics.Element = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var _ = Elm.Native.Utils(elm); var Native = Native||{};Native.Utils = _;
-  var guid = _.guid, max = _.max, htmlHeight = _.htmlHeight;
-  var JS = Elm.JavaScript(elm);
-  var List = Elm.List(elm);
-  var _ = Elm.Color(elm); var Color = _;
-  var _ = Elm.Maybe(elm); var Maybe = _;
-  var Just = _.Just, Nothing = _.Nothing;
-  var Image_14 = F4(function(a1, a2, a3, a4){
-    return {ctor:"Image", _0:a1, _1:a2, _2:a3, _3:a4};});
-  var Container_15 = F2(function(a1, a2){
-    return {ctor:"Container", _0:a1, _1:a2};});
-  var Flow_16 = F2(function(a1, a2){
-    return {ctor:"Flow", _0:a1, _1:a2};});
-  var Spacer_17 = {ctor:"Spacer"};
-  var RawHtml_18 = function(a1){
-    return {ctor:"RawHtml", _0:a1};};
-  var Custom_19 = {ctor:"Custom"};
-  var Plain_20 = {ctor:"Plain"};
-  var Fitted_21 = {ctor:"Fitted"};
-  var Cropped_22 = function(a1){
-    return {ctor:"Cropped", _0:a1};};
-  var Tiled_23 = {ctor:"Tiled"};
-  var P_28 = {ctor:"P"};
-  var Z_29 = {ctor:"Z"};
-  var N_30 = {ctor:"N"};
-  var Absolute_31 = function(a1){
-    return {ctor:"Absolute", _0:a1};};
-  var Relative_32 = function(a1){
-    return {ctor:"Relative", _0:a1};};
-  var DUp_36 = {ctor:"DUp"};
-  var DDown_37 = {ctor:"DDown"};
-  var DLeft_38 = {ctor:"DLeft"};
-  var DRight_39 = {ctor:"DRight"};
-  var DIn_40 = {ctor:"DIn"};
-  var DOut_41 = {ctor:"DOut"};
-  var Properties_0 = F7(function(id_73, width_74, height_75, opacity_76, color_77, href_78, tag_79){
-    return {
-      _:{
-      },
-      color:color_77,
-      height:height_75,
-      href:href_78,
-      id:id_73,
-      opacity:opacity_76,
-      tag:tag_79,
-      width:width_74};});
-  var Element_1 = F2(function(props_80, element_81){
-    return {
-      _:{
-      },
-      element:element_81,
-      props:props_80};});
-  var widthOf_2 = function(e_82){
-    return e_82.props.width;};
-  var heightOf_3 = function(e_83){
-    return e_83.props.height;};
-  var sizeOf_4 = function(e_84){
-    return {ctor:"Tuple2", _0:e_84.props.width, _1:e_84.props.height};};
-  var width_5 = F2(function(nw_85, e_86){
-    return function(){
-      var p_87 = e_86.props;
-      var props_88 = function(){ 
-      var case0 = e_86.element;
-      switch (case0.ctor) {
-        case 'Image':
-          return _N.replace([['height',((case0._2/case0._1)*nw_85)]], p_87);
-        case 'RawHtml':
-          return _N.replace([['height',function(){
-            var _50000_92 = A2(htmlHeight, nw_85, case0._0);
-            var w_93 = function(){ 
-            switch (_50000_92.ctor) {
-              case 'Tuple2':
-                return _50000_92._0;
-            }_E.Case('Line 50, Column 71') }();
-            var h_94 = function(){ 
-            switch (_50000_92.ctor) {
-              case 'Tuple2':
-                return _50000_92._1;
-            }_E.Case('Line 50, Column 71') }();
-            return h_94;}()]], p_87);
-      }
-      return p_87; }();
-      return {
-        _:{
-        },
-        element:e_86.element,
-        props:_N.replace([['width',nw_85]], props_88)};}();});
-  var height_6 = F2(function(nh_99, e_100){
-    return function(){
-      var p_101 = e_100.props;
-      var props_102 = function(){ 
-      var case12 = e_100.element;
-      switch (case12.ctor) {
-        case 'Image':
-          return _N.replace([['width',((case12._1/case12._2)*nh_99)]], p_101);
-      }
-      return p_101; }();
-      return {
-        _:{
-        },
-        element:e_100.element,
-        props:_N.replace([['height',nh_99]], p_101)};}();});
-  var size_7 = F3(function(w_105, h_106, e_107){
-    return A2(height_6, h_106, A2(width_5, w_105, e_107));});
-  var opacity_8 = F2(function(o_108, e_109){
-    return function(){
-      var p_110 = e_109.props;
-      return {
-        _:{
-        },
-        element:e_109.element,
-        props:_N.replace([['opacity',o_108]], p_110)};}();});
-  var color_9 = F2(function(c_111, e_112){
-    return function(){
-      var p_113 = e_112.props;
-      return {
-        _:{
-        },
-        element:e_112.element,
-        props:_N.replace([['color',Just(c_111)]], p_113)};}();});
-  var tag_10 = F2(function(name_114, e_115){
-    return function(){
-      var p_116 = e_115.props;
-      return {
-        _:{
-        },
-        element:e_115.element,
-        props:_N.replace([['tag',JS.fromString(name_114)]], p_116)};}();});
-  var link_11 = F2(function(href_117, e_118){
-    return function(){
-      var p_119 = e_118.props;
-      return {
-        _:{
-        },
-        element:e_118.element,
-        props:_N.replace([['href',JS.fromString(href_117)]], p_119)};}();});
-  var newElement_13 = F3(function(w_120, h_121, e_122){
-    return {
-      _:{
-      },
-      element:e_122,
-      props:A7(Properties_0, guid({ctor:"Tuple0"}), w_120, h_121, 1, Nothing, emptyStr_12, emptyStr_12)};});
-  var image_24 = F3(function(w_123, h_124, src_125){
-    return A3(newElement_13, w_123, h_124, A4(Image_14, Plain_20, w_123, h_124, JS.fromString(src_125)));});
-  var fittedImage_25 = F3(function(w_126, h_127, src_128){
-    return A3(newElement_13, w_126, h_127, A4(Image_14, Fitted_21, w_126, h_127, JS.fromString(src_128)));});
-  var croppedImage_26 = F4(function(pos_129, w_130, h_131, src_132){
-    return A3(newElement_13, w_130, h_131, A4(Image_14, Cropped_22(pos_129), w_130, h_131, JS.fromString(src_132)));});
-  var tiledImage_27 = F3(function(w_133, h_134, src_135){
-    return A3(newElement_13, w_133, h_134, A4(Image_14, Tiled_23, w_133, h_134, JS.fromString(src_135)));});
-  var Position_33 = F4(function(horizontal_136, vertical_137, x_138, y_139){
-    return {
-      _:{
-      },
-      horizontal:horizontal_136,
-      vertical:vertical_137,
-      x:x_138,
-      y:y_139};});
-  var container_34 = F4(function(w_140, h_141, pos_142, e_143){
-    return A3(newElement_13, w_140, h_141, A2(Container_15, pos_142, e_143));});
-  var spacer_35 = F2(function(w_144, h_145){
-    return A3(newElement_13, w_144, h_145, Spacer_17);});
-  var flow_42 = F2(function(dir_146, es_147){
-    return function(){
-      var newFlow_150 = F2(function(w_151, h_152){
-        return A3(newElement_13, w_151, h_152, A2(Flow_16, dir_146, es_147));});
-      var ws_148 = A2(List.map, widthOf_2, es_147);
-      var hs_149 = A2(List.map, heightOf_3, es_147);
-      return (_N.eq(es_147,_L.Nil)?A2(spacer_35, 0, 0):function(){ 
-      switch (dir_146.ctor) {
-        case 'DDown':
-          return A2(newFlow_150, List.maximum(ws_148), List.sum(hs_149));
-        case 'DIn':
-          return A2(newFlow_150, List.maximum(ws_148), List.maximum(hs_149));
-        case 'DLeft':
-          return A2(newFlow_150, List.sum(ws_148), List.maximum(hs_149));
-        case 'DOut':
-          return A2(newFlow_150, List.maximum(ws_148), List.maximum(hs_149));
-        case 'DRight':
-          return A2(newFlow_150, List.sum(ws_148), List.maximum(hs_149));
-        case 'DUp':
-          return A2(newFlow_150, List.maximum(ws_148), List.sum(hs_149));
-      }_E.Case('Line 160, Column 3') }());}();});
-  var above_43 = F2(function(hi_153, lo_154){
-    return A3(newElement_13, A2(max, widthOf_2(hi_153), widthOf_2(lo_154)), (heightOf_3(hi_153)+heightOf_3(lo_154)), A2(Flow_16, DDown_37, _L.Cons(hi_153,_L.Cons(lo_154,_L.Nil))));});
-  var below_44 = F2(function(lo_155, hi_156){
-    return A3(newElement_13, A2(max, widthOf_2(hi_156), widthOf_2(lo_155)), (heightOf_3(hi_156)+heightOf_3(lo_155)), A2(Flow_16, DDown_37, _L.Cons(hi_156,_L.Cons(lo_155,_L.Nil))));});
-  var beside_45 = F2(function(lft_157, rht_158){
-    return A3(newElement_13, (widthOf_2(lft_157)+widthOf_2(rht_158)), A2(max, heightOf_3(lft_157), heightOf_3(rht_158)), A2(Flow_16, right_70, _L.Cons(lft_157,_L.Cons(rht_158,_L.Nil))));});
-  var layers_46 = function(es_159){
-    return function(){
-      var ws_160 = A2(List.map, widthOf_2, es_159);
-      var hs_161 = A2(List.map, heightOf_3, es_159);
-      return A3(newElement_13, List.maximum(ws_160), List.maximum(hs_161), A2(Flow_16, DOut_41, es_159));}();};
-  var middleAt_58 = F2(function(x_162, y_163){
-    return {
-      _:{
-      },
-      horizontal:Z_29,
-      vertical:Z_29,
-      x:x_162,
-      y:y_163};});
-  var topLeftAt_59 = F2(function(x_164, y_165){
-    return {
-      _:{
-      },
-      horizontal:N_30,
-      vertical:P_28,
-      x:x_164,
-      y:y_165};});
-  var topRightAt_60 = F2(function(x_166, y_167){
-    return {
-      _:{
-      },
-      horizontal:P_28,
-      vertical:P_28,
-      x:x_166,
-      y:y_167};});
-  var bottomLeftAt_61 = F2(function(x_168, y_169){
-    return {
-      _:{
-      },
-      horizontal:N_30,
-      vertical:N_30,
-      x:x_168,
-      y:y_169};});
-  var bottomRightAt_62 = F2(function(x_170, y_171){
-    return {
-      _:{
-      },
-      horizontal:P_28,
-      vertical:N_30,
-      x:x_170,
-      y:y_171};});
-  var midLeftAt_63 = F2(function(x_172, y_173){
-    return {
-      _:{
-      },
-      horizontal:N_30,
-      vertical:Z_29,
-      x:x_172,
-      y:y_173};});
-  var midRightAt_64 = F2(function(x_174, y_175){
-    return {
-      _:{
-      },
-      horizontal:P_28,
-      vertical:Z_29,
-      x:x_174,
-      y:y_175};});
-  var midTopAt_65 = F2(function(x_176, y_177){
-    return {
-      _:{
-      },
-      horizontal:Z_29,
-      vertical:P_28,
-      x:x_176,
-      y:y_177};});
-  var midBottomAt_66 = F2(function(x_178, y_179){
-    return {
-      _:{
-      },
-      horizontal:Z_29,
-      vertical:N_30,
-      x:x_178,
-      y:y_179};});
-  var emptyStr_12 = JS.fromString(_str(''));
-  var absolute_47 = Absolute_31;
-  var relative_48 = Relative_32;
-  var middle_49 = {
-    _:{
-    },
-    horizontal:Z_29,
-    vertical:Z_29,
-    x:Relative_32(0.5),
-    y:Relative_32(0.5)};
-  var topLeft_50 = {
-    _:{
-    },
-    horizontal:N_30,
-    vertical:P_28,
-    x:Absolute_31(0),
-    y:Absolute_31(0)};
-  var topRight_51 = _N.replace([['horizontal',P_28]], topLeft_50);
-  var bottomLeft_52 = _N.replace([['vertical',N_30]], topLeft_50);
-  var bottomRight_53 = _N.replace([['horizontal',P_28]], bottomLeft_52);
-  var midLeft_54 = _N.replace([['horizontal',N_30],['x',Absolute_31(0)]], middle_49);
-  var midRight_55 = _N.replace([['horizontal',P_28]], midLeft_54);
-  var midTop_56 = _N.replace([['vertical',P_28],['y',Absolute_31(0)]], middle_49);
-  var midBottom_57 = _N.replace([['vertical',N_30]], midTop_56);
-  var up_67 = DUp_36;
-  var down_68 = DDown_37;
-  var left_69 = DLeft_38;
-  var right_70 = DRight_39;
-  var inward_71 = DIn_40;
-  var outward_72 = DOut_41;
-  elm.Native = elm.Native||{};
-  elm.Native.Graphics = elm.Native.Graphics||{};
-  var _ = elm.Native.Graphics.Element||{};
-  _.$op = {};
-  _.widthOf = widthOf_2;
-  _.heightOf = heightOf_3;
-  _.sizeOf = sizeOf_4;
-  _.width = width_5;
-  _.height = height_6;
-  _.size = size_7;
-  _.opacity = opacity_8;
-  _.color = color_9;
-  _.tag = tag_10;
-  _.link = link_11;
-  _.newElement = newElement_13;
-  _.image = image_24;
-  _.fittedImage = fittedImage_25;
-  _.croppedImage = croppedImage_26;
-  _.tiledImage = tiledImage_27;
-  _.container = container_34;
-  _.spacer = spacer_35;
-  _.flow = flow_42;
-  _.above = above_43;
-  _.below = below_44;
-  _.beside = beside_45;
-  _.layers = layers_46;
-  _.absolute = absolute_47;
-  _.relative = relative_48;
-  _.middle = middle_49;
-  _.topLeft = topLeft_50;
-  _.topRight = topRight_51;
-  _.bottomLeft = bottomLeft_52;
-  _.bottomRight = bottomRight_53;
-  _.midLeft = midLeft_54;
-  _.midRight = midRight_55;
-  _.midTop = midTop_56;
-  _.midBottom = midBottom_57;
-  _.middleAt = middleAt_58;
-  _.topLeftAt = topLeftAt_59;
-  _.topRightAt = topRightAt_60;
-  _.bottomLeftAt = bottomLeftAt_61;
-  _.bottomRightAt = bottomRightAt_62;
-  _.midLeftAt = midLeftAt_63;
-  _.midRightAt = midRightAt_64;
-  _.midTopAt = midTopAt_65;
-  _.midBottomAt = midBottomAt_66;
-  _.up = up_67;
-  _.down = down_68;
-  _.left = left_69;
-  _.right = right_70;
-  _.inward = inward_71;
-  _.outward = outward_72
-  elm.Graphics = elm.Graphics||{};
-  return elm.Graphics.Element = _;
-  };
-Elm.Graphics = Elm.Graphics||{};
-Elm.Graphics.Collage = function(elm){
-  var N = Elm.Native, _N = N.Utils(elm), _L = N.List(elm), _E = N.Error(elm), _str = N.JavaScript(elm).toString;
-  var $op = {};
-  var _ = Elm.List(elm); var List = _;
-  var _ = Elm.Native.Utils(elm); var Native = Native||{};Native.Utils = _;
-  var toFloat = _.toFloat;
-  var _ = Elm.Either(elm); var Either = _;
-  var Matrix = Elm.Native.Matrix2D(elm);
-  var N = Elm.Native.Graphics.Collage(elm);
-  var _ = Elm.Graphics.Element(elm); var Graphics = Graphics||{};Graphics.Element = _;
-  var _ = Elm.Color(elm); var Color = _;
-  var Solid_1 = function(a1){
-    return {ctor:"Solid", _0:a1};};
-  var Texture_2 = function(a1){
-    return {ctor:"Texture", _0:a1};};
-  var Gradient_3 = function(a1){
-    return {ctor:"Gradient", _0:a1};};
-  var Flat_4 = {ctor:"Flat"};
-  var Round_5 = {ctor:"Round"};
-  var Padded_6 = {ctor:"Padded"};
-  var Smooth_7 = {ctor:"Smooth"};
-  var Sharp_8 = function(a1){
-    return {ctor:"Sharp", _0:a1};};
-  var Clipped_9 = {ctor:"Clipped"};
-  var FPath_15 = F2(function(a1, a2){
-    return {ctor:"FPath", _0:a1, _1:a2};});
-  var FShape_16 = F2(function(a1, a2){
-    return {ctor:"FShape", _0:a1, _1:a2};});
-  var FImage_17 = F4(function(a1, a2, a3, a4){
-    return {ctor:"FImage", _0:a1, _1:a2, _2:a3, _3:a4};});
-  var FElement_18 = function(a1){
-    return {ctor:"FElement", _0:a1};};
-  var FGroup_19 = F2(function(a1, a2){
-    return {ctor:"FGroup", _0:a1, _1:a2};});
-  var Form_0 = F5(function(theta_44, scale_45, x_46, y_47, form_48){
-    return {
-      _:{
-      },
-      form:form_48,
-      scale:scale_45,
-      theta:theta_44,
-      x:x_46,
-      y:y_47};});
-  var LineStyle_10 = F6(function(color_49, width_50, cap_51, join_52, dashing_53, dashOffset_54){
-    return {
-      _:{
-      },
-      cap:cap_51,
-      color:color_49,
-      dashOffset:dashOffset_54,
-      dashing:dashing_53,
-      join:join_52,
-      width:width_50};});
-  var solid_12 = function(clr_55){
-    return _N.replace([['color',clr_55]], defaultLine_11);};
-  var dashed_13 = function(clr_56){
-    return _N.replace([['color',clr_56],['dashing',_L.Cons(8,_L.Cons(4,_L.Nil))]], defaultLine_11);};
-  var dotted_14 = function(clr_57){
-    return _N.replace([['color',clr_57],['dashing',_L.Cons(3,_L.Cons(3,_L.Nil))]], defaultLine_11);};
-  var form_20 = function(f_58){
-    return {
-      _:{
-      },
-      form:f_58,
-      scale:1,
-      theta:0,
-      x:0,
-      y:0};};
-  var fill_21 = F2(function(style_59, shape_60){
-    return form_20(A2(FShape_16, Either.Right(style_59), shape_60));});
-  var filled_22 = F2(function(color_61, shape_62){
-    return A2(fill_21, Solid_1(color_61), shape_62);});
-  var textured_23 = F2(function(src_63, shape_64){
-    return A2(fill_21, Texture_2(src_63), shape_64);});
-  var gradient_24 = F2(function(grad_65, shape_66){
-    return A2(fill_21, Gradient_3(grad_65), shape_66);});
-  var outlined_25 = F2(function(style_67, shape_68){
-    return form_20(A2(FShape_16, Either.Left(style_67), shape_68));});
-  var traced_26 = F2(function(style_69, path_70){
-    return form_20(A2(FPath_15, style_69, path_70));});
-  var sprite_27 = F4(function(w_71, h_72, pos_73, src_74){
-    return form_20(A4(FImage_17, w_71, h_72, pos_73, src_74));});
-  var toForm_28 = function(e_75){
-    return form_20(FElement_18(e_75));};
-  var group_29 = function(fs_76){
-    return form_20(A2(FGroup_19, Matrix.identity, fs_76));};
-  var groupTransform_30 = F2(function(matrix_77, fs_78){
-    return form_20(A2(FGroup_19, matrix_77, fs_78));});
-  var rotate_31 = F2(function(t_79, f_80){
-    return _N.replace([['theta',(f_80.theta+t_79)]], f_80);});
-  var scale_32 = F2(function(s_81, f_82){
-    return _N.replace([['scale',(f_82.scale*s_81)]], f_82);});
-  var move_33 = F2(function(_138000_83, f_84){
-    return function(){ 
-    switch (_138000_83.ctor) {
-      case 'Tuple2':
-        return _N.replace([['x',(f_84.x+_138000_83._0)],['y',(f_84.y+_138000_83._1)]], f_84);
-    }_E.Case('Line 138, Column 20') }();});
-  var moveX_34 = F2(function(x_87, f_88){
-    return _N.replace([['x',(f_88.x+x_87)]], f_88);});
-  var moveY_35 = F2(function(y_89, f_90){
-    return _N.replace([['y',(f_90.y+y_89)]], f_90);});
-  var path_36 = function(ps_91){
-    return ps_91;};
-  var segment_37 = F2(function(p1_92, p2_93){
-    return _L.Cons(p1_92,_L.Cons(p2_93,_L.Nil));});
-  var polygon_38 = function(points_94){
-    return points_94;};
-  var rect_39 = F2(function(w_95, h_96){
-    return function(){
-      var hw_97 = (w_95/2);
-      var hh_98 = (h_96/2);
-      return _L.Cons({ctor:"Tuple2", _0:(0-hw_97), _1:(0-hh_98)},_L.Cons({ctor:"Tuple2", _0:(0-hw_97), _1:hh_98},_L.Cons({ctor:"Tuple2", _0:hw_97, _1:hh_98},_L.Cons({ctor:"Tuple2", _0:hw_97, _1:(0-hh_98)},_L.Nil))));}();});
-  var square_40 = function(n_99){
-    return A2(rect_39, n_99, n_99);};
-  var oval_41 = F2(function(w_100, h_101){
-    return function(){
-      var f_106 = function(i_107){
-        return {ctor:"Tuple2", _0:(hw_104*Math.cos((t_103*i_107))), _1:(hh_105*Math.sin((t_103*i_107)))};};
-      var n_102 = 50;
-      var t_103 = ((2*Math.PI)/n_102);
-      var hw_104 = (w_100/2);
-      var hh_105 = (h_101/2);
-      return A2(List.map, f_106, _L.range(0,(n_102-1)));}();});
-  var circle_42 = function(r_108){
-    return A2(oval_41, (2*r_108), (2*r_108));};
-  var ngon_43 = F2(function(n_109, r_110){
-    return function(){
-      var f_113 = function(i_114){
-        return {ctor:"Tuple2", _0:(r_110*Math.cos((t_112*i_114))), _1:(r_110*Math.sin((t_112*i_114)))};};
-      var m_111 = toFloat(n_109);
-      var t_112 = ((2*Math.PI)/m_111);
-      return A2(List.map, f_113, _L.range(0,(n_109-1)));}();});
-  var defaultLine_11 = {
-    _:{
-    },
-    cap:Flat_4,
-    color:Color.black,
-    dashOffset:0,
-    dashing:_L.Nil,
-    join:Sharp_8(10),
-    width:1};
-  elm.Native = elm.Native||{};
-  elm.Native.Graphics = elm.Native.Graphics||{};
-  var _ = elm.Native.Graphics.Collage||{};
-  _.$op = {};
-  _.Form = Form_0;
-  _.Solid = Solid_1;
-  _.Texture = Texture_2;
-  _.Gradient = Gradient_3;
-  _.Flat = Flat_4;
-  _.Round = Round_5;
-  _.Padded = Padded_6;
-  _.Smooth = Smooth_7;
-  _.Sharp = Sharp_8;
-  _.Clipped = Clipped_9;
-  _.LineStyle = LineStyle_10;
-  _.defaultLine = defaultLine_11;
-  _.solid = solid_12;
-  _.dashed = dashed_13;
-  _.dotted = dotted_14;
-  _.FPath = FPath_15;
-  _.FShape = FShape_16;
-  _.FImage = FImage_17;
-  _.FElement = FElement_18;
-  _.FGroup = FGroup_19;
-  _.form = form_20;
-  _.fill = fill_21;
-  _.filled = filled_22;
-  _.textured = textured_23;
-  _.gradient = gradient_24;
-  _.outlined = outlined_25;
-  _.traced = traced_26;
-  _.sprite = sprite_27;
-  _.toForm = toForm_28;
-  _.group = group_29;
-  _.groupTransform = groupTransform_30;
-  _.rotate = rotate_31;
-  _.scale = scale_32;
-  _.move = move_33;
-  _.moveX = moveX_34;
-  _.moveY = moveY_35;
-  _.path = path_36;
-  _.segment = segment_37;
-  _.polygon = polygon_38;
-  _.rect = rect_39;
-  _.square = square_40;
-  _.oval = oval_41;
-  _.circle = circle_42;
-  _.ngon = ngon_43
-  elm.Graphics = elm.Graphics||{};
-  return elm.Graphics.Collage = _;
-  };
-(function() {
-'use strict';
-
-ElmRuntime.Display = { FULLSCREEN: 0, COMPONENT: 1, NONE: 2 };
-
-ElmRuntime.counter = 0;
-ElmRuntime.guid = function() { return ElmRuntime.counter++; }
-
-ElmRuntime.use = function(M) {
-    if (typeof M === 'function') M = M();
-    return M;
-};
-
-function isAlive(input) {
-    if (!('defaultNumberOfKids' in input)) return true;
-    var len = input.kids.length;
-    if (len === 0) return false;
-    if (len > input.defaultNumberOfKids) return true;
-    var alive = false;
-    for (var i = len; i--; ) {
-        alive = alive || isAlive(input.kids[i]);
-    }
-    return alive;
-}
-
-ElmRuntime.filterDeadInputs = function(inputs) {
-    var temp = [];
-    for (var i = inputs.length; i--; ) {
-        if (isAlive(inputs[i])) temp.push(inputs[i]);
-    }
-    return temp;
-};
-
-// define the draw function
-var vendors = ['ms', 'moz', 'webkit', 'o'];
-for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
-    window.requestAnimationFrame = window[vendors[i]+'RequestAnimationFrame'];
-    window.cancelAnimationFrame  = window[vendors[i]+'CancelAnimationFrame'] ||
-                                   window[vendors[i]+'CancelRequestAnimationFrame'];
-}
-
-if (window.requestAnimationFrame && window.cancelAnimationFrame) {
-    var previous = 0;
-    ElmRuntime.draw = function(callback) {
-        window.cancelAnimationFrame(previous);
-        previous = window.requestAnimationFrame(callback);
-    };
-} else {
-    ElmRuntime.draw = function(callback) { callback(); };
-}
-
-}());
-
-(function() {
-'use strict';
-
-Elm.fullscreen = function(module) {
-    var style = document.createElement('style');
-    style.type = 'text/css';
-    style.innerHTML = "html,head,body { padding:0; margin:0; }" +
-        "body { font-family: calibri, helvetica, arial, sans-serif; }";
-    document.head.appendChild(style);
-    var container = document.createElement('div');
-    document.body.appendChild(container);
-    return init(ElmRuntime.Display.FULLSCREEN, container, module);
-};
-
-Elm.byId = function(id, module) {
-    var container = document.getElementById(id);
-    var tag = container.tagName;
-    if (tag !== 'DIV') {
-        throw new Error('Elm.byId must be given a div, not a ' + tag + '.');
-    }
-    while (container.hasChildNodes()) {
-        container.removeChild(container.lastChild);
-    }
-    return init(ElmRuntime.Display.COMPONENT, container, module);
-};
-
-Elm.worker = function(module) {
-    return init(ElmRuntime.Display.NONE, {}, module);
-};
-
-function init(display, container, module) {
-  // defining state needed for an instance of the Elm RTS
-  var signalGraph = null;
-  var inputs = [];
-  var visualModel = null;
-
-  function notify(id, v) {
-    var timestep = Date.now();
-    var hasListener = false;
-    for (var i = inputs.length; i--; ) {
-      // must maintain the order of this stmt to avoid having the ||
-      // short-circuiting the necessary work of recv
-      hasListener = inputs[i].recv(timestep, id, v) || hasListener;
-    }
-    return hasListener;
-  }
-
-  container.offsetX = 0;
-  container.offsetY = 0;
-
-  // create the actual RTS. Any impure modules will attach themselves to this
-  // object. This permits many Elm programs to be embedded per document.
-  var elm = { notify:notify,
-              node:container,
-              display:display,
-              id:ElmRuntime.guid(),
-              inputs:inputs
-  };
-
-  // Set up methods to communicate with Elm program from JS.
-  function send(name, value) {
-      if (typeof value === 'undefined') return function(v) { return send(name,v); };
-      var e = document.createEvent('Event');
-      e.initEvent(name + '_' + elm.id, true, true);
-      e.value = value;
-      document.dispatchEvent(e);
-  }
-  function recv(name, handler) {
-      document.addEventListener(name + '_' + elm.id, handler);
-  }
-
-  recv('log', function(e) {console.log(e.value)});
-  recv('title', function(e) {document.title = e.value});
-  recv('redirect', function(e) {
-    if (e.value.length > 0) { window.location = e.value; }
-  });
-
-  // If graphics are not enabled, escape early, skip over setting up DOM stuff.
-  if (display === ElmRuntime.Display.NONE) {
-      module(elm);
-      return { send : send, recv : recv };
-  }
-
-  var Render = ElmRuntime.use(ElmRuntime.Render.Element);
-
-  // evaluate the given module and extract its 'main' value.
-  signalGraph = module(elm).main;
-
-  // make sure the signal graph is actually a signal, extract the visual model,
-  // and filter out any unused inputs.
-  var Signal = Elm.Signal(elm);
-  if (!('recv' in signalGraph)) signalGraph = Signal.constant(signalGraph);
-  visualModel = signalGraph.value;
-  inputs = ElmRuntime.filterDeadInputs(inputs);
-  
-   // Add the visualModel to the DOM
-  container.appendChild(Render.render(visualModel));
-  if (elm.Native.Window) elm.Native.Window.resizeIfNeeded();
-  
-  // set up updates so that the DOM is adjusted as necessary.
-  var update = Render.update;
-  function domUpdate(value) {
-      ElmRuntime.draw(function(_) {
-              update(container.firstChild, visualModel, value);
-              visualModel = value;
-              if (elm.Native.Window) elm.Native.Window.resizeIfNeeded();
-          });
-      return value;
-  }
-
-  signalGraph = A2(Signal.lift, domUpdate, signalGraph);
-    
-  return { send : send, recv : recv, node : container };
-};
-
-}());
-ElmRuntime.Render.Utils = function() {
-'use strict';
-
-function newElement(elementType) {
-    var e = document.createElement(elementType);    
-    e.style.padding = "0";
-    e.style.margin = "0";
-    return e;
-}
-
-function addTo(container, elem) {
-    container.appendChild(elem);
-}
-
-function extract(c) {
-    if (c._3 === 1) { return 'rgb(' + c._0 + ',' + c._1 + ',' + c._2 + ')'; }
-    return 'rgba(' + c._0 + ',' + c._1 + ',' + c._2 + ',' + c._3 + ')';
-}
-
-function addTransform(style, trans) {
-  style.transform       = trans;
-  style.msTransform     = trans;
-  style.MozTransform    = trans;
-  style.webkitTransform = trans;
-  style.OTransform      = trans;
-}
-
-function removeTransform(style) {
-  style.transform       = 'none';
-  style.msTransform     = 'none';
-  style.MozTransform    = 'none';
-  style.webkitTransform = 'none';
-  style.OTransform      = 'none';
-}
-
-var List = Elm.Native.List({});
-
-return {addTo:addTo,
-	newElement:newElement,
-	extract : extract,
-	fromList: List.toArray,
-	fromString: function(s) { return List.toArray(s).join(''); },
-	toString: List.fromArray,
-	eq: Elm.Native.Utils({}).eq,
-	addTransform: addTransform,
-	removeTransform: removeTransform
-	};
-};
-
-ElmRuntime.Render.Element = function() {
-'use strict';
-
-var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
-var newElement = Utils.newElement, extract = Utils.extract,
-    addTransform = Utils.addTransform, removeTransform = Utils.removeTransform,
-    fromList = Utils.fromList, eq = Utils.eq;
-
-function setProps(props, e) {
-    e.style.width  = (props.width |0) + 'px';
-    e.style.height = (props.height|0) + 'px';
-    if (props.opacity !== 1) { e.style.opacity = props.opacity; }
-    if (props.color.ctor === 'Just') {
-	e.style.backgroundColor = extract(props.color._0);
-    }
-    if (props.tag !== '') { e.id = props.tag; }
-    if (props.href !== '') {
-	var a = newElement('a');
-	a.href = props.href;
-	a.appendChild(e);
-	return a;
-    }
-    return e;
-}
-
-function image(props, img) {
-    switch (img._0.ctor) {
-    case 'Plain':   return plainImage(img._3);
-    case 'Fitted':  return fittedImage(props.width, props.height, img._3);
-    case 'Cropped': return croppedImage(img,props.width,props.height,img._3);
-    case 'Tiled':   return tiledImage(img._3);
-    }
-}
-
-function plainImage(src) {
-    var img = newElement('img');
-    img.src = src;
-    img.name = src;
-    img.style.display = "block";
-    return img;
-}
-
-function tiledImage(src) {
-    var div = newElement('div');
-    div.style.backgroundImage = 'url(' + src + ')';
-    return div;
-}
-
-function fittedImage(w, h, src) {
-    var div = newElement('div');
-    div.style.background = 'url(' + src + ') no-repeat center';
-    div.style.webkitBackgroundSize = 'cover';
-    div.style.MozBackgroundSize = 'cover';
-    div.style.OBackgroundSize = 'cover';
-    div.style.backgroundSize = 'cover';
-    return div;
-}
-
-function croppedImage(elem, w, h, src) {
-    var pos = elem._0._0;
-    var e = newElement('div');
-    e.style.position = "relative";
-    e.style.overflow = "hidden";
-
-    var img = newElement('img');
-    img.onload = function() {
-	img.style.position = 'absolute';
-	img.style.margin = 'auto';
-	var sw = w / elem._1, sh = h / elem._2;
-	img.style.width = ((this.width * sw)|0) + 'px';
-	img.style.height = ((this.height * sh)|0) + 'px';
-	img.style.left = ((- pos._0 * sw)|0) + 'px';
-	img.style.top = ((- pos._1 * sh)|0) + 'px';
-    };
-    img.src = src;
-    img.name = src;
-    e.appendChild(img);
-    return e;
-}
-
-function goIn(e) { e.style.position = 'absolute'; return e; }
-function goDown(e) { return e }
-function goRight(e) { e.style.styleFloat = e.style.cssFloat = "left"; return e; }
-function flowWith(f, array) {
-    var container = newElement('div');
-    for (var i = array.length; i--; ) {
-	container.appendChild(f(render(array[i])));
-    }
-    return container;
-}
-
-function flow(dir,elist) {
-    var array = fromList(elist);
-    switch(dir.ctor) {
-    case "DDown":  array.reverse();
-    case "DUp":    return flowWith(goDown,array);
-    case "DRight": array.reverse();
-    case "DLeft":  return flowWith(goRight,array);
-    case "DOut":   array.reverse();
-    case "DIn":    return flowWith(goIn,array);
-    }
-}
-
-function toPos(pos) {
-    switch(pos.ctor) {
-    case "Absolute": return  pos._0 + "px";
-    case "Relative": return (pos._0 * 100) + "%";
-    }
-}
-
-function setPos(pos,w,h,e) {
-    e.style.position = 'absolute';
-    e.style.margin = 'auto';
-    var transform = '';
-    switch(pos.horizontal.ctor) {
-    case 'P': e.style.right = toPos(pos.x); break;
-    case 'Z': transform = 'translateX(' + ((-w/2)|0) + 'px) ';
-    case 'N': e.style.left = toPos(pos.x); break;
-    }
-    switch(pos.vertical.ctor) {
-    case 'N': e.style.bottom = toPos(pos.y); break;
-    case 'Z': transform += 'translateY(' + ((-h/2)|0) + 'px)';
-    case 'P': e.style.top = toPos(pos.y); break;
-    }
-    if (transform !== '') addTransform(e.style, transform);
-    return e;
-}
-
-function container(pos,elem) {
-    var e = render(elem);
-    setPos(pos, elem.props.width, elem.props.height, e);
-    var div = newElement('div');
-    div.style.position = 'relative';
-    div.style.overflow = 'hidden';
-    div.appendChild(e);
-    return div;
-}
-
-function rawHtml(html) {
-    var e = newElement('div');
-    e.innerHTML = html;
-    return e;
-}
-
-function render(elem) { return setProps(elem.props, makeElement(elem)); }
-function makeElement(e) {
-    var elem = e.element;
-    switch(elem.ctor) {
-    case 'Image':     return image(e.props, elem);
-    case 'Flow':      return flow(elem._0, elem._1);
-    case 'Container': return container(elem._0, elem._1);
-    case 'Spacer':    return newElement('div');
-    case 'RawHtml':   return rawHtml(elem._0);
-    case 'Custom':    return elem.render(elem.model);
-    }
-}
-
-function update(node, curr, next) {
-    if (node.tagName === 'A') { node = node.firstChild; }
-    if (curr.props.id === next.props.id) return updateProps(node, curr, next);
-    if (curr.element.ctor !== next.element.ctor) {
-	node.parentNode.replaceChild(render(next),node);
-	return true;
-    }
-    var nextE = next.element, currE = curr.element;
-    switch(nextE.ctor) {
-    case "Spacer": break;
-    case "RawHtml":
-        if (nextE._0 !== currE._0) node.innerHTML = nextE._0;
-        break;
-    case "Image":
-	if (nextE._0.ctor !== 'Plain') {
-	    if (nextE._3 !== currE._3) node.src = nextE._3;
-	} else if (!eq(nextE,currE) ||
-		   next.props.width !== curr.props.width ||
-		   next.props.height !== curr.props.height) {
-	    node.parentNode.replaceChild(render(next),node);
-	    return true;
-	}
-	break;
-    case "Flow":
-        var arr = fromList(nextE._1);
-        for (var i = arr.length; i--; ) { arr[i] = arr[i].element.ctor; }
-	if (nextE._0.ctor !== currE._0.ctor) {
-	    node.parentNode.replaceChild(render(next),node);
-	    return true;
-	}
-	var nexts = fromList(nextE._1);
-	var kids = node.childNodes;
-	if (nexts.length !== kids.length) {
-	    node.parentNode.replaceChild(render(next),node);
-	    return true;
-	}
-	var currs = fromList(currE._1);
-	var goDir = function(x) { return x; };
-	switch(nextE._0.ctor) {
-	case "DDown":  case "DUp":   goDir = goDown; break;
-	case "DRight": case "DLeft": goDir = goRight; break;
-	case "DOut":   case "DIn":   goDir = goIn; break;
-	}
-	for (var i = kids.length; i-- ;) {
-	    update(kids[i],currs[i],nexts[i]);
-	    goDir(kids[i]);
-	}
-	break;
-    case "Container":
-	var inner = node.firstChild;
-	if (!update(inner, currE._1, nextE._1)) {
-	    if (nextE._0.horizontal.ctor !== currE._0.horizontal.ctor) {
-		inner.style.left = inner.style.right = 'none';
-		removeTransform(inner.style);
-	    }
-	    if (nextE._0.vertical.ctor !== currE._0.vertical.ctor) {
-		inner.style.top = inner.style.bottom = 'none';
-		removeTransform(inner.style);
-	    }
-	}
-	setPos(nextE._0, nextE._1.props.width, nextE._1.props.height, inner);
-	break;
-    case "Custom":
-	if (currE.type === nextE.type) {
-	    var done = nextE.update(node, currE.model, nextE.model);
-	    if (done) return;
-	} else {
-	    return node.parentNode.replaceChild(render(next), node);
-	}
-    }
-    updateProps(node, curr, next);
-}
-
-function updateProps(node, curr, next) {
-    var props = next.props, currP = curr.props, e = node;
-    if (props.width !== currP.width)   e.style.width  = (props.width |0) + 'px';
-    if (props.height !== currP.height) e.style.height = (props.height|0) + 'px';
-    if (props.opacity !== 1 && props.opacity !== currP.opacity) {
-	e.style.opacity = props.opacity;
-    }
-    var nextColor = (props.color.ctor === 'Just' ?
-		     extract(props.color._0) : 'transparent');
-    if (e.style.backgroundColor !== nextColor) {
-        e.style.backgroundColor = nextColor;
-    }
-    if (props.tag !== currP.tag) { e.id = props.tag; }
-    if (props.href !== currP.href) {
-	if (currP.href === '') {
-	    var a = newElement('a');
-	    a.href = props.href;
-	    a.appendChild(e);
-	    e.parentNode.replaceChild(a,e);
-	} else {
-	    node.parentNode.href = props.href;
-	}
-    }
-}
-
-return { render:render, update:update };
-
-};
-ElmRuntime.Render.Collage = function() {
-'use strict';
-
-var Render = ElmRuntime.use(ElmRuntime.Render.Element);
-var Matrix = Elm.Matrix2D({});
-var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
-var newElement = Utils.newElement,
-    extract = Utils.extract, fromList = Utils.fromList,
-    fromString = Utils.fromString, addTransform = Utils.addTransform;
-
-function trace(ctx, path) {
-    var points = fromList(path);
-    var i = points.length - 1;
-    if (i <= 0) return;
-    ctx.moveTo(points[i]._0, points[i]._1);
-    while (i--) { ctx.lineTo(points[i]._0, points[i]._1); }
-    if (path.closed) {
-        i = points.length - 1;
-        ctx.lineTo(points[i]._0, points[i]._1);
-    }
-}
-
-function line(ctx,style,path) {
-    style.dashing.ctor === 'Nil' ? trace(ctx, path) : customLineHelp(ctx, style, path);
-    ctx.stroke();
-}
-
-function customLineHelp(ctx, style, path) {
-    var points = fromList(path);
-    if (path.closed) points.push(points[0]);
-    var pattern = fromList(style.dashing);
-    var i = points.length - 1;
-    if (i <= 0) return;
-    var x0 = points[i]._0, y0 = points[i]._1;
-    var x1=0, y1=0, dx=0, dy=0, remaining=0, nx=0, ny=0;
-    var pindex = 0, plen = pattern.length;
-    var draw = true, segmentLength = pattern[0];
-    ctx.moveTo(x0,y0);
-    while (i--) {
-        x1 = points[i]._0; y1 = points[i]._1;
-        dx = x1 - x0; dy = y1 - y0;
-        remaining = Math.sqrt(dx * dx + dy * dy);
-        while (segmentLength <= remaining) {
-            x0 += dx * segmentLength / remaining;
-            y0 += dy * segmentLength / remaining;
-            ctx[draw ? 'lineTo' : 'moveTo'](x0, y0);
-            // update starting position
-            dx = x1 - x0; dy = y1 - y0;
-            remaining = Math.sqrt(dx * dx + dy * dy);
-            // update pattern
-            draw = !draw;
-            pindex = (pindex + 1) % plen;
-            segmentLength = pattern[pindex];
-        }
-        if (remaining > 0) {
-            ctx[draw ? 'lineTo' : 'moveTo'](x1, y1);
-            segmentLength -= remaining;
-        }
-        x0 = x1; y0 = y1;
-    }
-}
-
-function drawLine(ctx, style, path) {
-    ctx.lineWidth = style.width;
-    var cap = style.cap.ctor;
-    ctx.lineCap = cap === 'Flat' ? 'butt' :
-                  cap === 'Round' ? 'round' : 'square';
-    var join = style.join.ctor;
-    ctx.lineJoin = join === 'Smooth' ? 'round' :
-                   join === 'Sharp' ? 'miter' : 'bevel';
-    ctx.miterLimit = style.join._0 || 10;
-    ctx.strokeStyle = extract(style.color);
-    return line(ctx, style, path);
-}
-
-function texture(redo, ctx, src) {
-    var img = new Image();
-    img.src = fromString(src);
-    img.onload = redo;
-    return ctx.createPattern(img, 'repeat');
-}
-
-function gradient(ctx, grad) {
-  var g;
-  var stops = [];
-  if (grad.ctor === 'Linear') {
-    var p0 = grad._0, p1 = grad._1;
-    g = ctx.createLinearGradient(p0._0, -p0._1, p1._0, -p1._1);
-    stops = fromList(grad._2);
-  } else {
-    var p0 = grad._0, p2 = grad._2;
-    g = ctx.createRadialGradient(p0._0, -p0._1, grad._1, p2._0, -p2._1, grad._3);
-    stops = fromList(grad._4);
-  }
-  var len = stops.length;
-  for (var i = 0; i < len; ++i) {
-    var stop = stops[i];
-    g.addColorStop(stop._0, extract(stop._1));
-  }
-  return g;
-}
-
-function drawShape(redo, ctx, style, path) {
-    trace(ctx, path);
-    var sty = style.ctor;
-    ctx.fillStyle =
-        sty === 'Solid' ? extract(style._0) :
-        sty === 'Texture' ? texture(redo, ctx, style._0) : gradient(ctx, style._0);
-    ctx.fill();
-}
-
-function drawImage(redo, ctx, form) {
-    var img = new Image();
-    img.onload = redo;
-    img.src = fromString(form._3);
-    var w = form._0,
-        h = form._1,
-        pos = form._2,
-        srcX = pos._0,
-        srcY = pos._1,
-        srcW = w,
-        srcH = h,
-        destX = -w/2,
-        destY = -h/2,
-        destW = w,
-        destH = h;
-
-    ctx.drawImage(img, srcX, srcY, srcW, srcH, destX, destY, destW, destH);
-}
-
-function renderForm(redo, ctx, form) {
-    ctx.save();
-    var x = form.x, y = form.y, theta = form.theta, scale = form.scale;
-    if (x !== 0 || y !== 0) ctx.translate(x, y);
-    if (theta !== 0) ctx.rotate(theta);
-    ctx.scale(scale,-scale);
-    ctx.beginPath();
-    var f = form.form;
-    switch(f.ctor) {
-    case 'FPath' : drawLine(ctx, f._0, f._1); break;
-    case 'FImage': drawImage(redo, ctx, f); break;
-    case 'FShape':
-	if (f._0.ctor === 'Left') {
-	    f._1.closed = true;
-	    drawLine(ctx, f._0._0, f._1);
-	} else {
-            drawShape(redo, ctx, f._0._0, f._1);
-        }
-	break;
-    }
-    ctx.restore();
-}
-
-function formToMatrix(form) {
-   var scale = form.scale;
-   var matrix = A6( Matrix.matrix, scale, 0, 0, scale, scale * form.x, scale * form.y );
-
-   var theta = form.theta
-   if (theta !== 0)
-       matrix = A2( Matrix.multiply, matrix, Matrix.rotation(theta) );
-
-   return matrix;
-}
-
-function makeTransform(w, h, form, matrices) {
-    var props = form.form._0.props;
-    var m = A6( Matrix.matrix, 1, 0, 0, 1,
-                (w - props.width)/2,
-                (h - props.height)/2 );
-    var len = matrices.length;
-    for (var i = 0; i < len; ++i) { m = A2( Matrix.multiply, m, matrices[i] ); }
-    m = A2( Matrix.multiply, m, formToMatrix(form) );
-
-    return 'matrix(' +   m[0]  + ',' +   m[3]  + ',' +
-                       (-m[1]) + ',' + (-m[4]) + ',' +
-                         m[2]  + ',' +   m[5]  + ')';
-}
-
-function stepperHelp(list) {
-    var arr = fromList(list);
-    var i = 0;
-    function peekNext() {
-        return i < arr.length ? arr[i].form.ctor : '';
-    }
-    // assumes that there is a next element
-    function next() {
-        var out = arr[i];
-        ++i;
-        return out;
-    }
-    return { peekNext:peekNext, next:next };
-}
-
-function stepper(forms) {
-    var ps = [stepperHelp(forms)];
-    var matrices = [];
-    function peekNext() {
-        var len = ps.length;
-        var formType = '';
-        for (var i = 0; i < len; ++i ) {
-            if (formType = ps[i].peekNext()) return formType;
-        }
-        return '';
-    }
-    // assumes that there is a next element
-    function next(ctx) {
-        while (!ps[0].peekNext()) { ps.shift(); matrices.pop(); ctx.restore(); }
-        var out = ps[0].next();
-        var f = out.form;
-        if (f.ctor === 'FGroup') {
-            ps.unshift(stepperHelp(f._1));
-            var m = A2( Matrix.multiply, f._0, formToMatrix(out));
-            ctx.save();
-            ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
-            matrices.push(m);
-        }
-        return out;
-    }
-    function transforms() { return matrices; }
-    return { peekNext:peekNext, next:next, transforms:transforms };
-}
-
-function makeCanvas(w,h) {
-    var canvas = newElement('canvas');
-    canvas.style.width  = w + 'px';
-    canvas.style.height = h + 'px';
-    canvas.style.display = "block";
-    canvas.style.position = "absolute";
-    canvas.width  = w;
-    canvas.height = h;
-    return canvas;
-}
-
-function render(model) {
-    var div = newElement('div');
-    update(div, model, model);
-    return div;
-}
-
-function updateTracker(w,h,div) {
-    var kids = div.childNodes;
-    var i = 0;
-    function transform(transforms, ctx) {
-        ctx.translate(w/2, h/2);
-        var len = transforms.length;
-        for (var i = 0; i < len; ++i) {
-            var m = transforms[i];
-            ctx.save();
-            ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
-        }
-        return ctx;
-    }
-    function getContext(transforms) {
-        while (i < kids.length) {
-            var node = kids[i++];
-            if (node.getContext) {
-                node.width = w;
-                node.height = h;
-                node.style.width = w + 'px';
-                node.style.height = h + 'px';
-                return transform(transforms, node.getContext('2d'));
-            }
-            div.removeChild(node);
-        }
-        var canvas = makeCanvas(w,h);
-        div.appendChild(canvas);
-        // we have added a new node, so we must step our position
-        ++i;
-        return transform(transforms, canvas.getContext('2d'));
-    }
-    function element(matrices, form) {
-        var container = kids[i];
-        if (!container || container.getContext) {
-            container = newElement('div');
-            container.style.overflow = 'hidden';
-            container.style.position = 'absolute';
-            addTransform(container.style, 'scaleY(-1)');
-            if (!container) {
-                div.appendChild(container);
-            } else {
-                var kid = kids[i];
-                if (kid) {
-                    div.insertBefore(container, kid);
-                } else {
-                    div.appendChild(container);
-                }
-            }
-        }
-        // we have added a new node, so we must step our position
-        ++i;
-
-        container.style.width = w + 'px';
-        container.style.height = h + 'px';
-
-        var elem = form.form._0;
-        var node = container.firstChild;
-        if (node) {
-            Render.update(node, node.oldElement, elem);
-            node = container.firstChild;
-        } else {
-            node = Render.render(elem);
-            container.appendChild(node);
-        }
-        node.oldElement = elem;
-        addTransform(node.style, makeTransform(w, h, form, matrices));
-    }
-    return { getContext:getContext, element:element };
-}
-
-
-function update(div, _, model) {
-    var w = model.w;
-    var h = model.h;
-    div.style.width = w + 'px';
-    div.style.height = h + 'px';
-    if (model.forms.ctor === 'Nil') {
-        while (div.hasChildNodes()) {
-            div.removeChild(div.lastChild);
-        }
-    }
-    var stpr = stepper(model.forms);
-    var tracker = updateTracker(w,h,div);
-    var ctx = null;
-    var formType = '';
-
-    while (formType = stpr.peekNext()) {
-        if (ctx === null && formType !== 'FElement') {
-            ctx = tracker.getContext(stpr.transforms());
-            ctx.scale(1,-1);
-        }
-        var form = stpr.next(ctx);
-        if (formType === 'FElement') {
-            tracker.element(stpr.transforms(), form);
-            ctx = null;
-        } else if (formType !== 'FGroup') {
-            renderForm(function() { update(div, model, model); }, ctx, form);
-        }
-    }
-    return div;
-}
-
-return { render:render, update:update };
-
-};
diff --git a/tests/Everything.hs b/tests/Everything.hs
new file mode 100644
--- /dev/null
+++ b/tests/Everything.hs
@@ -0,0 +1,7 @@
+module Everything where
+
+import System.Exit
+
+main = do
+  putStrLn "This test always fails"
+  exitFailure
