diff --git a/getopt-generics.cabal b/getopt-generics.cabal
--- a/getopt-generics.cabal
+++ b/getopt-generics.cabal
@@ -3,7 +3,7 @@
 -- see: https://github.com/sol/cabalize
 
 name:           getopt-generics
-version:        0.4.1
+version:        0.5
 synopsis:       Simple command line argument parsing
 description:
   "getopt-generics" tries to make it very simple to create command line argument parsers. An introductory example can be found in the <https://github.com/zalora/getopt-generics#getopt-generics README>.
diff --git a/src/System/Console/GetOpt/Generics.hs b/src/System/Console/GetOpt/Generics.hs
--- a/src/System/Console/GetOpt/Generics.hs
+++ b/src/System/Console/GetOpt/Generics.hs
@@ -7,6 +7,7 @@
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE GADTs                 #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverlappingInstances  #-}
 {-# LANGUAGE RankNTypes            #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
 {-# LANGUAGE TypeFamilies          #-}
@@ -270,12 +271,11 @@
 
 -- | Type class for all allowed field types.
 --
---   Implementing custom instances to allow different types is possible. In the
---   easiest case you just implement 'argumentType' and 'parseArgument' (the
---   minimal complete definition).
---
---   (Unfortunately implementing instances for lists or 'Maybe's of custom types
---   is not very straightforward.)
+--   If you want to use custom field types you should implement an
+--   @instance Option YourCustomType@ containing implementations of
+--   'argumentType' and 'parseArgument' (the minimal complete definition). For
+--   an example see the
+--   <https://github.com/zalora/getopt-generics#getopt-generics README>.
 class Typeable a => Option a where
   {-# MINIMAL argumentType, parseArgument #-}
   -- | Name of the argument type, e.g. "bool" or "integer".
@@ -320,36 +320,25 @@
   _toOption = NoArg (FieldSuccess True)
   _emptyOption _ = FieldSuccess False
 
-instance Option String where
-  argumentType _ = "string"
-  parseArgument = Just
+instance Option a => Option [a] where
+  argumentType Proxy = argumentType (Proxy :: Proxy a) ++ " (multiple possible)"
+  parseArgument x = case parseArgument x of
+    Just (x :: a) -> Just [x]
+    Nothing -> Nothing
+  _emptyOption _ = FieldSuccess []
+  _accumulate = (++)
 
-instance Option (Maybe String) where
-  argumentType _ = "string (optional)"
-  parseArgument = Just . Just
+instance Option a => Option (Maybe a) where
+  argumentType Proxy = argumentType (Proxy :: Proxy a) ++ " (optional)"
+  parseArgument x = case parseArgument x of
+    Just (x :: a) -> Just (Just x)
+    Nothing -> Nothing
   _emptyOption _ = FieldSuccess Nothing
 
-instance Option [String] where
-  argumentType _ = "string (multiple possible)"
-  parseArgument = Just . pure
-  _emptyOption _ = FieldSuccess []
-  _accumulate = (++)
+instance Option String where
+  argumentType Proxy = "string"
+  parseArgument = Just
 
 instance Option Int where
   argumentType _ = "integer"
   parseArgument = readMaybe
-
-instance Option (Maybe Int) where
-  argumentType _ = "integer (optional)"
-  parseArgument s = case readMaybe s of
-    Just i -> Just (Just i)
-    Nothing -> Nothing
-  _emptyOption _ = FieldSuccess Nothing
-
-instance Option [Int] where
-  argumentType _ = "integer (multiple possible)"
-  parseArgument s = case readMaybe s of
-    Just a -> Just [a]
-    Nothing -> Nothing
-  _emptyOption _ = FieldSuccess []
-  _accumulate = (++)
