diff --git a/Example.hs b/Example.hs
new file mode 100644
--- /dev/null
+++ b/Example.hs
@@ -0,0 +1,8 @@
+-- | Simple example, demonstrating the usage
+--   This requires the first arg to be an int, and the second to be a string.
+import System.SimpleArgs
+
+main = do
+  (i,name) <- getArgs
+  print (i+10::Int)
+  print ("Hello, "++name++"!")
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,74 @@
+
+SimpleArgs - provide a more flexible and informative replacement for getArgs 
+
+For "real" command line programs, you usually want to provide a
+flexible command line with various options and settings, sensibly
+named and with auto-generated help.  In that case, SimpleArgs is not
+for you, stop reading this, and look up System.Console.GetOpt
+instead. 
+
+But sometimes, a quick hack is just what you need.  Previously, you
+were wont to do:
+
+      main = do
+      	   [count',gender'] <- getArgs
+	   let count = read count
+	   let gender = case gender' of 
+	       	      	     "M" -> 'M'
+			     "F" -> 'F'
+	   main_real count gender
+
+This is somewhat tedious, wastes precious sceen estate, users
+supplying parameters of the wrong type will get obscure errors, and
+while any programming errors you might introduce probably will be
+trivial, it would be better to avoid them entirely.
+
+The SimpleArgs module provides getArgs with an overloaded return type,
+so that command line parameters are parsed as the types required by
+the rest of the program.
+
+Using SimpleArgs, the above could therefore look like this:
+
+      main = do 
+      	   (count,gender) <- getArgs
+	   main_real count gender
+
+or even (I think):
+
+      main = getArgs >>= return . uncurry main_real
+
+If that was a bit contrieved, let's say you just want to read a file
+name:
+
+     main = do
+     	  [filename] <- getArgs
+	  readFile filename >>= print . length 
+
+I'm sure you could avoid the information-free name "filename" by some
+esoteric tranformation to more point-free style, but I argue that
+SimpleArgs makes this natural and easy:
+
+     main = getArgs >>= readFile >>= print . length
+
+I don't think 'wc -c' gets much easier than this.
+
+Instead of reporting incomplete cases or read failures, SimpleArgs
+will provide more sensible error reporting. (To try this, build Example
+by executing 'ghc --make Example.hs').  It will:
+
+      1) report incorrect number of parameters,
+      	 also mentioning the expected parameters and types:
+
+	  % ./Example foo
+	  Example: Incorrect number of arguments, got 1,
+	  expected 2 (Int,[Char])
+
+	This also gives you a useful hint if you just run the program
+	without any parameters.
+
+      2) report parameters that fail to parse as the required type:
+
+          % ./Example foo 10
+ 	  Example: Couldn't parse parameter "foo" as type Int
+
+Nice, huh?  Please enjoy, and let me know how you fare at ketil@malde.org.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,5 @@
+#!/usr/bin/env runhaskell
+
+import Distribution.Simple
+main = defaultMain
+
diff --git a/System/SimpleArgs.hs b/System/SimpleArgs.hs
new file mode 100644
--- /dev/null
+++ b/System/SimpleArgs.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# OPTIONS -fallow-undecidable-instances  -fno-monomorphism-restriction -fallow-overlapping-instances #-}
+
+-- | Provide a @getArgs@ function that returns a tuple (including the 0-tuple @()@ or 1-tuple)
+--   if the supplied arguments match the demands of the program, in number and in type. 
+--   The returned tuple must contain elements that are in the @Typeable@ and @Read@ classes.
+--
+-- Here's how to do a line count, @getArgs@ takes a single argument, returning it
+-- as a @String@:
+-- 
+-- > main = getArgs >>= readFile >>= print . length . lines
+--
+-- Two different parameters, a @Char@ and a @String@:
+--
+-- > main = do
+-- >    (ch,name) <- getArgs
+-- >    putStrLn (ch:"Name is: "++name)
+
+module System.SimpleArgs (Args, getArgs) where
+
+import qualified System.Environment as S (getArgs)
+import Data.Dynamic (Typeable, typeOf)
+
+class Args a where
+    -- | Return appropriately typed program arguments.
+    getArgs :: IO a
+
+argerror :: Typeable a => Int -> [String] -> a
+argerror n xs = let ret = error ("Incorrect number of arguments, got "++show (length xs)++",\n"
+                                ++"expected "++show n ++ " "++show (typeOf ret))
+                in ret
+
+instance Args () where
+    getArgs = S.getArgs >>= return . g
+        where g [] = ()
+              g xs = argerror 0 xs
+
+instance (Read b, Typeable b) => Args b where
+    getArgs = S.getArgs >>= return . g
+        where g [x] = myread x
+              g xs = argerror 1 xs
+
+instance (Read x, Typeable x, Read y, Typeable y) => Args (x,y) where
+    getArgs = S.getArgs >>= return . g
+        where g [x1,x2] = (myread x1,myread x2)
+              g xs = argerror 2 xs
+
+instance (Read t1, Typeable t1,Read t2, Typeable t2,Read t3, Typeable t3) => Args (t1,t2,t3) where
+    getArgs = S.getArgs >>= return . g
+        where g [x1,x2,x3] = (myread x1,myread x2,myread x3)
+              g xs = argerror 3 xs
+
+instance (Read t1,Typeable t1,Read t2,Typeable t2,Read t3,Typeable t3,Read t4,Typeable t4) => Args (t1,t2,t3,t4) where
+    getArgs = S.getArgs >>= return . g
+        where g [x1,x2,x3,x4] = (myread x1,myread x2,myread x3,myread x4)
+              g xs = argerror 4 xs
+
+instance (Read t1,Typeable t1,Read t2,Typeable t2,Read t3,Typeable t3,Read t4,Typeable t4,Read t5,Typeable t5) => Args (t1,t2,t3,t4,t5) where
+    getArgs = S.getArgs >>= return . g
+        where g [x1,x2,x3,x4,x5] = (myread x1,myread x2,myread x3,myread x4,myread x5)
+              g xs = argerror 5 xs
+
+-- | Attempt to parse the parameter as various types
+myread :: (Typeable a, Read a) => String -> a
+myread s = let ret = case map reads [s,sq s,dq s,lq s] of
+                       ([(x,"")]:_) -> x
+                       (_:[(c,"")]:_) -> c
+                       (_:_:[(str,"")]:_) -> str
+                       (_:_:_:[(l,"")]:_) -> l
+                       _ -> error ("Couldn't parse parameter "++show s++" as type "++show (typeOf ret))
+           in ret
+    where
+      -- different types of quoting
+      sq x = "'"++x++"'"
+      dq x = "\""++x++"\""
+      lq x = "["++x++"]"
diff --git a/simpleargs.cabal b/simpleargs.cabal
new file mode 100644
--- /dev/null
+++ b/simpleargs.cabal
@@ -0,0 +1,24 @@
+Name:         simpleargs
+Version:      0.1
+License:      LGPL
+
+Author:       Ketil Malde <ketil@malde.org>
+Stability:    Beta
+Synopsis:     Provides a more flexible getArgs function with better error reporting.
+Description:  The provided getArgs returns an arbitrary tuple of values instead of a 
+	      list of Strings.  This means that the number and type (i.e. parseability)
+	      of parameters are checked, and reported to the user.  The module is not
+	      a substitute for proper error handling (use System.Console.GetOpt for that),
+	      but is useful for making quick and dirty command line tools a bit less dirty,
+	      without sacrificing the quick part.
+Homepage:     http://malde.org/~ketil/simpleargs
+
+Build-Depends:  base
+Build-Type:     Simple
+Tested-With:    GHC==6.8.2
+
+ghc-options:      -Wall
+Include-Dirs:     .
+Exposed-Modules:    System.SimpleArgs
+Extra-Source-Files: Example.hs
+Data-Files:         README
