diff --git a/.travis.yml b/.travis.yml
new file mode 100644
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,56 @@
+# NB: don't set `language: haskell` here
+
+# The following enables several GHC versions to be tested; often it's enough to test only against the last release in a major GHC version. Feel free to omit lines listings versions you don't need/want testing for.
+env:
+# - GHCVER=6.12.3
+# - GHCVER=7.0.1
+# - GHCVER=7.0.2
+# - GHCVER=7.0.3
+# - GHCVER=7.0.4
+# - GHCVER=7.2.1
+# - GHCVER=7.2.2
+# - GHCVER=7.4.1
+ - GHCVER=7.4.2
+# - GHCVER=7.6.1
+# - GHCVER=7.6.2
+ - GHCVER=7.6.3
+# - GHCVER=7.8.1 # see note about Alex/Happy
+# - GHCVER=7.8.2 # see note about Alex/Happy
+ - GHCVER=7.8.3 # see note about Alex/Happy
+# - GHCVER=head  # see section about GHC HEAD snapshots
+
+# Note: the distinction between `before_install` and `install` is not important.
+before_install:
+ - travis_retry sudo add-apt-repository -y ppa:hvr/ghc
+ - travis_retry sudo apt-get update
+ - travis_retry sudo apt-get install cabal-install-1.18 ghc-$GHCVER # see note about happy/alex
+ - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/1.18/bin:$PATH
+ - |
+   if [ $GHCVER = "head" ] || [ ${GHCVER%.*} = "7.8" ]; then
+     travis_retry sudo apt-get install happy-1.19.3 alex-3.1.3
+     export PATH=/opt/alex/3.1.3/bin:/opt/happy/1.19.3/bin:$PATH
+   else
+     travis_retry sudo apt-get install happy alex
+   fi
+
+install:
+ - cabal update
+ - cabal install --only-dependencies --enable-tests -v2  # -v2 provides useful information for debugging
+
+# Here starts the actual work to be performed for the package under test; any command which exits with a non-zero exit code causes the build to fail.
+script:
+ - cabal configure --enable-tests -v2  # -v2 provides useful information for debugging
+ - cabal build   # this builds all libraries and executables (including tests/benchmarks)
+ - cabal test
+ - cabal check
+ - cabal sdist   # tests that a source-distribution can be generated
+
+# The following scriptlet checks that the resulting source distribution can be built & installed
+ - export SRC_TGZ=$(cabal-1.18 info . | awk '{print $2 ".tar.gz";exit}') ;
+   cd dist/;
+   if [ -f "$SRC_TGZ" ]; then
+      cabal install "$SRC_TGZ";
+   else
+      echo "expected '$SRC_TGZ' not found";
+      exit 1;
+   fi
diff --git a/PTQ.cabal b/PTQ.cabal
--- a/PTQ.cabal
+++ b/PTQ.cabal
@@ -1,5 +1,5 @@
 Name:            PTQ
-Version:         0.0.5
+Version:         0.0.6
 License:         LGPL
 License-File:    COPYING
 Author:          Masahiro Sakai
@@ -9,21 +9,27 @@
 Build-Type:      Simple
 Synopsis:        An implementation of Montague's PTQ.
 Description:     An implementation of Montague's PTQ (Proper Treatment of Quantification). It translates simple plain English sentences into formulas of intentional logic.
-Cabal-Version:   >= 1.2.3
+Cabal-Version:   >= 1.6
 Stability:       experimental
 Extra-Source-Files:
-   README, COPYING
+   README.md, COPYING, .travis.yml,
    src/Context.hs, src/MP.hs, src/PDict.hs, src/ParserTest.hs,
    misc/Test.hs, misc/Test2.agda, misc/Test3.hs
 Data-Files: cgi/index.html, cgi/main.html
 
+Source-Repository head
+  Type:     git
+  Location: git://github.com/msakai/ptq.git
+
 Flag UTF8Terminal
   Description: Use UTF-8 for terminal I/O
   Default: False
+  Manual: True
 
 Flag UTF8CGI
   Description: Use UTF-8 for HTTP contents
   Default: True
+  Manual: True
 
 Executable ptq
   Main-Is: Main.hs
@@ -41,10 +47,9 @@
      MultiParamTypeClasses
      TypeOperators
      TypeSynonymInstances
-  Build-Depends: base >=4 && <5, haskell98, mtl, containers
+  Build-Depends: base >=4.4 && <5, mtl, containers
   if flag(UTF8Terminal)
     CPP-Options: "-DUSE_UTF8"
-    Build-Depends: utf8-string
 
 Executable ptq.cgi
   Main-Is: CGIMain.hs
@@ -58,14 +63,15 @@
      ReportHTML
      CGI
      URLEncoding
-  Extensions:
+  Other-Extensions:
      EmptyDataDecls
      GADTs
      MultiParamTypeClasses
      TypeOperators
      TypeSynonymInstances
+     ScopedTypeVariables
+     FlexibleInstances
      CPP
-  Build-Depends: base >=4 && <5, haskell98, mtl, containers, network, xml
+  Build-Depends: base >=4.4 && <5, mtl, containers, network, xml
   if flag(UTF8CGI)
     CPP-Options: "-DUSE_UTF8"
-    Build-Depends: utf8-string
diff --git a/README b/README
deleted file mode 100644
--- a/README
+++ /dev/null
@@ -1,41 +0,0 @@
-= An implementation of Montague's PTQ in Haskell
-
-== Build and Install
-
-You'll need GHC 6.7 or later.
-
-  % runhaskell Setup.lhs configure
-  % runhaskell Setup.lhs build
-  % runhaskell Setup.lhs install
-
-== Usage of interactive shell ptq
-
-  % ptq
-  PTQ> John seeks a unicorn.
-  Parsed:
-    F4 john (F5 seek (F2 a unicorn))
-  
-  Translation:
-    (\x0. x0 {john}) (Int (seek (Int ((\x0. \x1. exists x2. x0 {x2} && x1 {x2}) (Int unicorn)))))
-  
-  Translation (simplified):
-    seek (Int (\x0. exists x1. unicorn x1 && x0 {x1})) john
-  
-  ------------------------------------------------------
-  
-  Parsed:
-    F10 0 (F2 a unicorn) (F4 john (F5 seek (He 0)))
-  
-  Translation:
-    (\x0. \x1. exists x2. x0 {x2} && x1 {x2}) (Int unicorn) (Int (\x0. (\x1. x1 {john}) (Int (seek (Int (\x1. x1 {x0}))))))
-  
-  Translation (simplified):
-    exists x0. unicorn x0 && seek (Int (\x1. x1 {x0})) john
-  PTQ> quit
-  %
-
-== CGI interface
-
-By locating ptq.cgi, cgi/index.html and cgi/main.html to the place
-where CGI is executable, you can try it on the web.
-Demo site runs at <http://www.tom.sfc.keio.ac.jp/~sakai/hsPTQ/>.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,45 @@
+An implementation of Montague's PTQ in Haskell
+==============================================
+
+[![Build Status](https://secure.travis-ci.org/msakai/ptq.png?branch=master)](http://travis-ci.org/msakai/ptq)
+
+Build and Install
+-----------------
+
+    % cabal configure
+    % cabal build
+    % cabal install
+
+Usage of interactive shell ptq
+------------------------------
+
+    % ptq
+    PTQ> John seeks a unicorn.
+    Parsed:
+      F4 john (F5 seek (F2 a unicorn))
+    
+    Translation:
+      (\x0. x0 {john}) (Int (seek (Int ((\x0. \x1. exists x2. x0 {x2} && x1 {x2}) (Int unicorn)))))
+    
+    Translation (simplified):
+      seek (Int (\x0. exists x1. unicorn x1 && x0 {x1})) john
+    
+    ------------------------------------------------------
+    
+    Parsed:
+      F10 0 (F2 a unicorn) (F4 john (F5 seek (He 0)))
+    
+    Translation:
+      (\x0. \x1. exists x2. x0 {x2} && x1 {x2}) (Int unicorn) (Int (\x0. (\x1. x1 {john}) (Int (seek (Int (\x1. x1 {x0}))))))
+    
+    Translation (simplified):
+      exists x0. unicorn x0 && seek (Int (\x1. x1 {x0})) john
+    PTQ> quit
+    %
+
+CGI interface
+-------------
+
+By locating ptq.cgi, cgi/index.html and cgi/main.html to the place
+where CGI is executable, you can try it on the web.
+Demo site runs at <http://www.tom.sfc.keio.ac.jp/~sakai/hsPTQ/>.
diff --git a/src/CGI.hs b/src/CGI.hs
--- a/src/CGI.hs
+++ b/src/CGI.hs
@@ -24,30 +24,33 @@
 module CGI
   (runCGI,
    HTTPRequest, varExist, lookupVar, lookupVars,
-   HTTPResponse(..), httpResponseToString, textContentType) where
+   HTTPResponse(..), textContentType) where
 
 import URLEncoding
 import Data.Maybe
 import Control.Monad
 import System.IO
+import System.IO.Error
 import System.Environment
-#ifdef USE_UTF8
-import qualified Codec.Binary.UTF8.String as UTF8
-#endif
 
 runCGI :: (HTTPRequest -> IO HTTPResponse) -> IO ()
 runCGI f = do hSetBinaryMode stdin True
-              hSetBinaryMode stdout True
+              -- hSetBinaryMode stdout True
+              hSetEncoding stdout utf8
+              hSetNewlineMode stdout noNewlineTranslation
               input <- getContents
               env <- cgiEnvs
-              res <- f (parseCGIRequest env input)
-              putStr (httpResponseToString' res)
+              res@(HTTPResponse ctype body) <- f (parseCGIRequest env input)
+              putStr $ "Content-Type: " ++ ctype ++ "\r\n"
+              putStr "\r\n"
+              putStr body
 
 cgiEnvs = return . catMaybes =<< mapM mGetEnvPair names
   where
     mGetEnvPair :: String -> IO (Maybe (String, String))
-    mGetEnvPair name = catch (return . Just . (,) name =<< getEnv name)
-                             (const $ return Nothing)
+    mGetEnvPair name =
+      catchIOError (return . Just . (,) name =<< getEnv name)
+                   (const $ return Nothing)
 
     names = [ "SERVER_NAME", "SERVER_PORT",
               "SERVER_SOFTWARE", "SERVER_PROTOCOL",
@@ -114,26 +117,5 @@
     resContentType :: String,
     resBody :: String
 }
-
-instance Show HTTPResponse where
-    show = httpResponseToString
-
-httpResponseToString (HTTPResponse ctype body) =
-  concat [ "Content-Type: ", ctype, "\r\n",
-           "Content-Length: ", show (length body), "\r\n",
-           "\r\n",
-           body ]
-
-#ifdef USE_UTF8
-httpResponseToString' (HTTPResponse ctype body) =
-  concat [ "Content-Type: ", ctype, "\r\n",
-           "Content-Length: ", show (length body'), "\r\n",
-           "\r\n",
-           body' ]
-  where
-    body' = UTF8.encodeString body
-#else
-httpResponseToString' = httpResponseToString
-#endif
 
 textContentType typ encoding = concat [typ, "; charset=\"", encoding, "\""]
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -8,17 +8,10 @@
 -- Stability   :  experimental
 -- Portability :  non-portable
 
-{-# LANGUAGE CPP #-}
 module Main where
 import Report
 import Version
-#ifdef USE_UTF8
-import Prelude hiding (putStr, putStrLn, getLine)
-import System.IO (stdout, hSetBuffering, BufferMode (..))
-import System.IO.UTF8
-#else
 import System.IO
-#endif
 
 main :: IO ()
 main = do
diff --git a/src/P.hs b/src/P.hs
--- a/src/P.hs
+++ b/src/P.hs
@@ -9,7 +9,7 @@
 -- Portability :  non-portable
 
 {-# LANGUAGE TypeOperators, GADTs, EmptyDataDecls, MultiParamTypeClasses
-  , TypeSynonymInstances #-}
+  , TypeSynonymInstances, FlexibleInstances #-}
 
 module P
   ( Sen
diff --git a/src/Parser.hs b/src/Parser.hs
--- a/src/Parser.hs
+++ b/src/Parser.hs
@@ -8,10 +8,11 @@
 -- Stability   :  experimental
 -- Portability :  non-portable
 
-{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE GADTs, TypeOperators #-}
 module Parser (parse, parseAny) where
 
 import Data.Char
+import Control.Applicative
 import Control.Monad
 import qualified Data.IntSet as IS
 
@@ -27,6 +28,17 @@
     { runParser :: Env -> State -> [Token] -> [(a, State, [Token])]
     }
 
+instance Functor Parser where
+    fmap = liftM
+
+instance Applicative Parser where
+    pure  = return
+    (<*>) = ap
+
+instance Alternative Parser where
+    empty = mzero
+    (<|>) = mplus
+
 instance Monad Parser where
     return x = Parser $ \_ s ts -> [(x,s,ts)]
     m >>= f = Parser $ \env s ts ->
@@ -38,10 +50,6 @@
     mplus x y = Parser $ \env s ts ->
                 runParser x env s ts ++ runParser y env s ts
 
-infixr 0 <|>
-(<|>) :: Parser a -> Parser a -> Parser a
-(<|>) = mplus
-
 anyToken :: Parser Token
 anyToken = Parser g
     where g _ _ []     = []
@@ -186,13 +194,6 @@
     do y <- anyToken
        guard $ x==y
        return y
-
-many, many1 :: Parser a -> Parser [a]
-many p = many1 p <|> return []
-many1 p =
-    do x  <- p
-       xs <- many p
-       return (x:xs)
 
 chainr1 :: Parser a -> Parser (a->a->a) -> Parser a
 chainr1 p q =
