diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2019, David Ogborn
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Language/Haskellish.hs b/Language/Haskellish.hs
new file mode 100644
--- /dev/null
+++ b/Language/Haskellish.hs
@@ -0,0 +1,161 @@
+module Language.Haskellish where
+
+import Language.Haskell.Exts
+import Control.Applicative
+import Data.Either (isRight)
+import Data.Maybe (catMaybes)
+
+
+data Haskellish a = Haskellish { runHaskellish :: Exp SrcSpanInfo -> Either String a }
+
+
+instance Functor Haskellish where
+  fmap f x = Haskellish (fmap f . runHaskellish x)
+
+
+instance Applicative Haskellish where
+  pure x = Haskellish (const (Right x))
+  f <*> x = Haskellish (\e -> do -- ie. in (Either String) monad
+    (e1,e2) <- applicationExpressions e
+    f' <- runHaskellish f e1
+    x' <- runHaskellish x e2
+    return (f' x')
+    )
+
+
+applicationExpressions :: Exp SrcSpanInfo -> Either String (Exp SrcSpanInfo,Exp SrcSpanInfo)
+applicationExpressions (Paren _ x) = applicationExpressions x
+applicationExpressions (App _ e1 e2) = Right (e1,e2)
+applicationExpressions (InfixApp _ e1 (QVarOp _ (UnQual _ (Symbol _ "$"))) e2) = Right (e1,e2)
+applicationExpressions (InfixApp l e1 (QVarOp _ (UnQual _ (Symbol _ x))) e2) = Right (App l x' e1,e2)
+  where x' = (Var l (UnQual l (Ident l x)))
+applicationExpressions (LeftSection l e1 (QVarOp _ (UnQual _ (Symbol _ x)))) = Right (x',e1)
+  where x' = (Var l (UnQual l (Ident l x)))
+applicationExpressions _ = Left ""
+
+
+instance Alternative Haskellish where
+  empty = Haskellish (const (Left ""))
+  a <|> b = Haskellish (\e -> do
+    let a' = runHaskellish a e
+    if isRight a' then a' else runHaskellish b e
+    )
+
+
+instance Monad Haskellish where
+  x >>= f = Haskellish (\e -> do
+    x' <- runHaskellish x e
+    runHaskellish (f x') e
+    )
+
+
+identifier :: Haskellish String -- note: we don't distinguish between identifiers and symbols
+identifier = Haskellish f
+  where f (Paren _ x) = f x
+        f (Var _ (UnQual _ (Ident _ x))) = Right x
+        f (Var _ (UnQual _ (Symbol _ x))) = Right x
+        f _ = Left ""
+
+reserved :: String -> Haskellish ()
+reserved x = Haskellish (\e -> do -- in (Either String)
+   e' <- runHaskellish identifier e
+   if e' == x then Right () else Left ""
+   )
+
+string :: Haskellish String
+string = Haskellish f
+  where f (Paren _ x) = f x
+        f (Lit _ (String _ x _)) = Right x
+        f _ = Left ""
+
+integer :: Haskellish Integer
+integer = Haskellish f
+  where f (Paren _ x) = f x
+        f (NegApp _ (Lit _ (Int _ x _))) = Right (x * (-1))
+        f (Lit _ (Int _ x _)) = Right x
+        f _ = Left ""
+
+rational :: Haskellish Rational
+rational = Haskellish f
+  where f (Paren _ x) = f x
+        f (NegApp _ (Lit _ (Frac _ x _))) = Right (x * (-1))
+        f (Lit _ (Frac _ x _)) = Right x
+        f _ = Left ""
+
+rationalOrInteger :: Haskellish Rational
+rationalOrInteger = Haskellish f
+  where f (Paren _ x) = f x
+        f (NegApp _ (Lit _ (Frac _ x _))) = Right (x * (-1))
+        f (Lit _ (Frac _ x _)) = Right x
+        f (NegApp _ (Lit _ (Int _ x _))) = Right (fromIntegral $ x * (-1))
+        f (Lit _ (Int _ x _)) = Right $ fromIntegral x
+        f _ = Left ""
+
+list :: Haskellish a -> Haskellish [a]
+list p = Haskellish (\e -> f e >>= mapM (runHaskellish p))
+  where
+    f (Paren _ x) = f x
+    f (List _ xs) = Right xs
+    f _ = Left ""
+
+tuple :: Haskellish a -> Haskellish b -> Haskellish (a,b)
+tuple p1 p2 = Haskellish (\e -> do
+  (a,b) <- f e
+  a' <- runHaskellish p1 a
+  b' <- runHaskellish p2 b
+  return (a',b')
+  )
+  where
+    f (Paren _ x) = f x
+    f (Tuple _ Boxed (a:b:[])) = Right (a,b)
+    f _ = Left ""
+
+asRightSection :: Haskellish (a -> b -> c) -> Haskellish b -> Haskellish (a -> c)
+asRightSection opP bP = Haskellish (\e -> do
+  (opExp,bExp) <- f e
+  op <- runHaskellish opP opExp
+  b <- runHaskellish bP bExp
+  return $ flip op b
+  )
+  where
+    f (Paren _ x) = f x
+    f (RightSection _ (QVarOp l (UnQual _ (Symbol _ x))) e1) = Right (g l x,e1)
+    f _ = Left ""
+    g l x = (Var l (UnQual l (Ident l x)))
+
+
+collectDoStatements :: Exp SrcSpanInfo -> [Exp SrcSpanInfo]
+collectDoStatements (Do _ xs) = catMaybes $ fmap f xs
+  where
+    f (Qualifier _ e) = Just e
+    f _ = Nothing
+
+listOfDoStatements :: Haskellish a -> Haskellish [a]
+listOfDoStatements p = Haskellish (\e -> mapM (runHaskellish p) $ collectDoStatements e)
+
+type Span = ((Int,Int),(Int,Int))
+
+askSpan :: Haskellish Span
+askSpan = Haskellish $ return . expToSpan
+
+expToSpan :: Exp SrcSpanInfo -> Span
+expToSpan (Var x _) = srcSpanInfoToSpan x
+expToSpan (Paren x _) = srcSpanInfoToSpan x
+expToSpan (App x _ _) = srcSpanInfoToSpan x
+expToSpan (InfixApp x _ _ _) = srcSpanInfoToSpan x
+expToSpan (LeftSection x _ _) = srcSpanInfoToSpan x
+expToSpan (NegApp x _) = srcSpanInfoToSpan x
+expToSpan (Lit x _) = srcSpanInfoToSpan x
+expToSpan (List x _) = srcSpanInfoToSpan x
+expToSpan (RightSection x _ _) = srcSpanInfoToSpan x
+expToSpan (Tuple x _ _) = srcSpanInfoToSpan x
+expToSpan (Do x _) = srcSpanInfoToSpan x
+expToSpan _ = ((0,0),(0,0))
+
+srcSpanInfoToSpan :: SrcSpanInfo -> Span
+srcSpanInfoToSpan x = ((bx,by),(ex,ey))
+  where
+    bx = srcSpanStartColumn $ srcInfoSpan x
+    by = srcSpanStartLine $ srcInfoSpan x
+    ex = srcSpanEndColumn $ srcInfoSpan x
+    ey = srcSpanEndLine $ srcInfoSpan x
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/haskellish.cabal b/haskellish.cabal
new file mode 100644
--- /dev/null
+++ b/haskellish.cabal
@@ -0,0 +1,33 @@
+name:                haskellish
+version:             0.1.0
+synopsis:            For parsing Haskell-ish languages
+homepage:            http://github.com/dktr0/Haskellish
+license:             BSD3
+license-file:        LICENSE
+author:              David Ogborn
+maintainer:          David Ogborn <ogbornd@mcmaster.ca>
+Stability:           Experimental
+Copyright:           (c) 2019- David Ogborn
+Category:            Language
+Build-type:          Simple
+cabal-version:       >=1.10
+tested-with:         GHC == 8.6.3
+
+Description: A library for parsing miniature and esoteric languages that are similar to Haskell
+
+library
+  ghc-options: -Wall
+  hs-source-dirs:
+                 .
+
+  default-language:    Haskell2010
+
+  Exposed-modules:     Language.Haskellish
+
+  Build-depends:
+      base >=4.8 && <5
+    , haskell-src-exts >=1.17.1 && <1.23
+
+source-repository head
+  type:     git
+  location: https://github.com/dktr0/Haskellish
