diff --git a/Text/Formlets.hs b/Text/Formlets.hs
--- a/Text/Formlets.hs
+++ b/Text/Formlets.hs
@@ -73,8 +73,9 @@
          fromLeft n _               = Failure [n ++ " is a file."]
 
 -- | A File input widget.
-inputFile :: Monad m => (String -> xml)  -- | Generates the xml for the file-upload widget based on the name
-                     -> Form xml m File
+inputFile :: Monad m 
+          => (String -> xml)  -- | Generates the xml for the file-upload widget based on the name
+          -> Form xml m File
 inputFile i = Form $ \env -> mkInput env <$> freshName
   where  mkInput env name    = (return . fromRight name . (lookup name), i name, MultiPart)
          fromRight n Nothing          = Failure [n ++ " is not in the data"]
diff --git a/Text/XHtml/Strict/Formlets.hs b/Text/XHtml/Strict/Formlets.hs
--- a/Text/XHtml/Strict/Formlets.hs
+++ b/Text/XHtml/Strict/Formlets.hs
@@ -6,8 +6,10 @@
 
 import Text.Formlets
 import qualified Text.XHtml.Strict as X
-import Text.XHtml.Strict ((!), (+++))
+import Text.XHtml.Strict ((!), (+++), (<<))
+import Control.Applicative
 import Control.Applicative.Error
+import Data.List (elemIndex)
 
 type XHtmlForm m a = Form X.Html m a
 
@@ -54,3 +56,19 @@
                                 `check` convert `check` tryToEnum
  where toS = fmapFst (show . fromEnum)
        convert v = maybeRead' v "Conversion error" 
+
+selectRaw :: Monad m => [(String, String)] -> Maybe String -> XHtmlForm m String
+selectRaw choices = input' mkChoices -- todo: validate that the result was in the choices
+ where mkChoices name selected = X.select ! [X.name name] $ X.concatHtml $ map (mkChoice selected) choices
+       mkChoice  selected (value, label) = X.option ! (attrs ++ [X.value value]) << label
+        where attrs | selected == value = [X.selected]
+                    | otherwise = []
+
+-- | A drop-down for anything that is an instance of Eq
+select :: (Eq a, Monad m) => [(a, String)] -> Maybe a -> XHtmlForm m a
+select ls v = selectRaw (map f $ zip [0..] ls) selected `check` asInt `check` convert
+ where selected       = show <$> (v >>= flip elemIndex (map fst ls))
+       f (idx, (_,l)) = (show idx, l)
+       convert i      | i >= length ls || i < 0 = Failure ["Out of bounds"]
+                      | otherwise               = Success $ fst $ ls !! i
+       asInt   s      = maybeRead' s (s ++ " is not a valid int")
diff --git a/formlets.cabal b/formlets.cabal
--- a/formlets.cabal
+++ b/formlets.cabal
@@ -1,5 +1,5 @@
 Name:            formlets
-Version:         0.4.3
+Version:         0.4.4
 Synopsis:        Formlets implemented in Haskell
 Description:     A modular way to build forms based on applicative functors, as
                  described in:
