diff --git a/Text/Digestive/HSP/Html4.hs b/Text/Digestive/HSP/Html4.hs
--- a/Text/Digestive/HSP/Html4.hs
+++ b/Text/Digestive/HSP/Html4.hs
@@ -3,28 +3,29 @@
 module Text.Digestive.HSP.Html4 where
 
 import Control.Applicative             ((<$>))
-import Data.Maybe                      (fromMaybe)
+import Control.Monad                   (mplus)
+import Data.Maybe                      (fromMaybe, mapMaybe)
 import Data.Monoid                     (Monoid(mempty), mconcat)
 import Data.Text                       (Text)
 import qualified Data.Text             as Text
 import HSP                             (XMLGenerator, XMLGenT, EmbedAsChild(..), EmbedAsAttr(..), Attr(..), genElement, genEElement, set)
 import qualified HSX.XMLGenerator      as HSX
-import Text.Digestive                   -- (Form, mapViews)
-import Text.Digestive.Common           as Common        -- (Form, mapViews)
-import Text.Digestive.Forms            as Forms -- (inputString, inputRead, inputBool, inputChoice)
-
+import Text.Digestive                  (FormId, Form(..), Result(..), View(..), getFormId, getFormInput, isFormInput, mapView)
+import Text.Digestive.Common           as Common
+import Text.Digestive.Forms            as Forms
 
 showFormId :: FormId -> String
 showFormId id' = show id'
 
+-- text input box that returns a 'String'
 inputString :: (Monad m, Functor m, XMLGenerator x, FormInput i f)
-          => Maybe String
+          => Maybe String -- ^ initial value
           -> Form m i e [XMLGenT x (HSX.XML x)] String
 inputString = 
     Forms.inputString $ \id' inp ->
         [<input type="text" name=(showFormId id') id=(showFormId id') value=(fromMaybe "" inp) />]
 
--- FIMXE: we really need a inputText primitive on Common. or maybe inputByteString?
+-- FIXME: use inputText from Forms when it becomes available
 inputText :: (Monad m, Functor m, XMLGenerator x, FormInput i f)
           => Maybe Text
           -> Form m i e [XMLGenT x (HSX.XML x)] Text
@@ -34,11 +35,11 @@
             [<input type="text" name=(showFormId id') id=(showFormId id') value=(fromMaybe "" inp) />]) (Text.unpack <$> v))
 
 inputTextArea :: (Monad m, Functor m, XMLGenerator x, FormInput i f) =>
-                 Maybe Int
-              -> Maybe Int
+                 Maybe Int -- ^ cols
+              -> Maybe Int -- ^ rows
               -> Maybe String
               -> Form m i e [XMLGenT x (HSX.XML x)] String
-inputTextArea r c = 
+inputTextArea c r = 
     Forms.inputString $ \id' inp ->
         [<textarea name=(showFormId id') id=(showFormId id') (rows r ++ cols c)><% fromMaybe "" inp %></textarea>]
     where
@@ -61,18 +62,41 @@
     flip Forms.inputString Nothing $ \id' inp ->
         [<input type="password" name=(showFormId id') id=(showFormId id') value=(fromMaybe "" inp) />]
 
+checked True = [("checked" := "checked")]
+checked False = []
+
+selected True = [("selected" := "selected")]
+selected False = []
+
 inputCheckBox :: (Monad m, Functor m, XMLGenerator x, FormInput i f)
               => Bool
               -> Form m i e [XMLGenT x (HSX.XML x)] Bool
 inputCheckBox inp =
     flip inputBool inp $ \id' inp ->
-        [<input type="checkbox" name=(showFormId id') id=(showFormId id') checked />]
-    where
-      checked =
-          if inp
-          then [("checked" := "checked")]
-          else []
+        [<input type="checkbox" name=(showFormId id') id=(showFormId id') (checked inp) />]
 
+inputCheckboxes :: (Monad m, Functor m, Eq a, XMLGenerator x, EmbedAsChild x c, Monoid c, FormInput i f)
+           => Bool                                 -- ^ Use @<br>@ tags
+           -> [a]                                  -- ^ Default option
+           -> [(a, c)]                             -- ^ Choices with their names
+           -> Form m i e [XMLGenT x (HSX.XML x)] [a] -- ^ Resulting form
+inputCheckboxes br defs choices =
+    inputChoices toView defs (map fst choices)
+  where
+    toView group' id' sel val =
+        [ <input type="checkbox" name=(showFormId group') id=id' value=id' (checked sel) />
+        , <label for=id'><% fromMaybe mempty $ lookup val choices %></label>
+        ] ++ if br then [<br />] else []
+
+-- | radio buttons
+--
+-- NOTE:
+--
+-- According to the spec
+-- <http://www.w3.org/TR/html401/interact/forms.html#h-17.2.1> radio
+-- buttons should be able to have an undefined state. But since
+-- user-agents are inconsistent about handling undefined, it is
+-- recommended that a default option always be provided.
 inputRadio :: (Monad m, Functor m, Eq a, XMLGenerator x, EmbedAsChild x c, Monoid c, FormInput i f)
            => Bool                                 -- ^ Use @<br>@ tags
            -> a                                    -- ^ Default option
@@ -82,9 +106,36 @@
     inputChoice toView def (map fst choices)
   where
     toView group' id' sel val =
-        [ <input type="radio" name=(showFormId group') id=id' value=id' />
+        [ <input type="radio" name=(showFormId group') id=id' value=id' (checked sel) />
         , <label for=id'><% fromMaybe mempty $ lookup val choices %></label>
         ] ++ if br then [<br />] else []
+
+inputSelect :: (Monad m, Functor m, Eq a, XMLGenerator x, EmbedAsChild x c, Monoid c, FormInput i f)
+           => a                                    -- ^ Default option
+           -> [(a, c)]                             -- ^ Choices with their names
+           -> Form m i e [XMLGenT x (HSX.XML x)] a -- ^ Resulting form
+inputSelect def choices = 
+    Form $ do id' <- getFormId
+              unForm $ mapView (\cs -> [<select name=(showFormId id') id=(showFormId id')><% cs %></select>])
+                         (inputChoice toView def (map fst choices))
+  where
+    toView group' id' sel val =
+        [ <option id=id' value=id' (selected sel)><% fromMaybe mempty $ lookup val choices %></option>]
+
+inputMultiSelect :: (Monad m, Functor m, Eq a, XMLGenerator x, EmbedAsChild x c, Monoid c, FormInput i f)
+           => [a]                                  -- ^ Default options
+           -> [(a, c)]                             -- ^ Choices with their names
+           -> Form m i e [XMLGenT x (HSX.XML x)] [a] -- ^ Resulting form
+inputMultiSelect defs choices = 
+    Form $ do id' <- getFormId
+              unForm $ mapView (\cs -> [<select multiple="" name=(showFormId id') id=(showFormId id')><% cs %></select>])
+                         (inputChoices toView defs (map fst choices))
+  where
+    toView group' id' sel val =
+        [ <option id=id' value=id' (selected sel)><% fromMaybe mempty $ lookup val choices %></option>]
+
+
+
 submit :: (Monad m, Functor m, XMLGenerator x, FormInput i f)
           => String
           -> Form m i e [XMLGenT x (HSX.XML x)] String
@@ -92,7 +143,19 @@
     Forms.inputString (\id' inp ->
         [<input type="submit" name=(showFormId id') id=(showFormId id') value=(fromMaybe "" inp) />]) (Just v)
 
-
+-- TODO: add hiddenText when new digestive functors is availabe on hackage that adds Forms.inputText
+inputHiddenString :: (Monad m, Functor m, XMLGenerator x, FormInput i f)
+          => String
+          -> Form m i e [XMLGenT x (HSX.XML x)] String
+inputHiddenString str = 
+    Forms.inputString 
+             (\id' inp ->
+                  [<input type="hidden" name=(show id') id=(show id') value=(fromMaybe "" inp) />])
+             (Just str)
+-- | file upload form
+inputFile :: (Monad m, Functor m, XMLGenerator x, FormInput i f) => 
+             Form m i e [XMLGenT x (HSX.XML x)] (Maybe f)
+inputFile = Forms.inputFile $ \id' -> [<input type="file" name=(show id') id=(show id') />]
 
 label :: (Monad m, XMLGenerator x, EmbedAsChild x c, EmbedAsAttr x (Attr String String))
       => c
@@ -139,3 +202,45 @@
          -> attr 
          -> Form m i e [HSX.GenXML x] a
 setAttrs form attrs = mapView (map (`set` attrs)) form
+
+inputChoices :: (Monad m, Functor m, FormInput i f, Monoid v, Eq a)
+            => (FormId -> String -> Bool -> a -> v)  -- ^ Choice constructor
+            -> [a]                                   -- ^ Default options
+            -> [a]                                   -- ^ Choices
+            -> Form m i e v [a]                      -- ^ Resulting form
+inputChoices toView defaults choices = Form $ do
+    inputKeys <- maybe [] getInputStrings <$> getFormInput
+    id' <- getFormId
+    formInput <- isFormInput
+    let -- Find the actual input, based on the key, or use the default input
+        inps = if formInput 
+               then mapMaybe (\inputKey -> lookup inputKey $ zip (ids id') choices) inputKeys
+               else defaults
+        -- Apply the toView' function to all choices
+        view' = mconcat $ zipWith (toView' id' inps) (ids id') choices
+    return (View (const view'), Ok inps)
+  where
+    ids id' = map (((show id' ++ "-") ++) . show) [1 .. length choices]
+    toView' id' inps key x = toView id' key (x `elem` inps) x
+
+lookups :: (Eq a) => a -> [(a, b)] -> [b]
+lookups a = map snd . filter ((== a) . fst)
+
+-- |simple wrapper that creates form tag with the following attributes
+--
+-- @action=action@
+--
+-- @method="POST"@
+--
+-- @enctype="multipart/form-data"
+--
+-- @accept-charset="UTF-8"
+--
+form :: (XMLGenerator x, EmbedAsAttr x (Attr String action), EmbedAsChild x c) => 
+        action -- ^ value for action attribute
+     -> c      -- ^ contents of form tag
+     -> XMLGenT x (HSX.XML x)
+form action xml = 
+    <form action=action method="POST" enctype="multipart/form-data" accept-charset="UTF-8">
+      <% xml %>
+    </form>
diff --git a/digestive-functors-hsp.cabal b/digestive-functors-hsp.cabal
--- a/digestive-functors-hsp.cabal
+++ b/digestive-functors-hsp.cabal
@@ -1,5 +1,5 @@
 Name:                digestive-functors-hsp
-Version:             0.2.1
+Version:             0.4.3
 Synopsis:            HSP support for digestive-functors
 Description:         This is an HSP frontend for the digestive-functors library.
 Homepage:            http://src.seereason.com/digestive-functors-hsp
@@ -8,14 +8,14 @@
 Author:              Jeremy Shaw
 Maintainer:          jeremy@n-heptane.com
 Category:            Web
-Build-type:          Simple
+Build-type:          Custom
 Cabal-version:       >=1.6
 
 
 Library
   Exposed-modules:     Text.Digestive.HSP.Html4
   Build-depends:       base == 4.*,
-                       digestive-functors == 0.0.2.*,
+                       digestive-functors == 0.1.*,
                        hsp,
                        hsx,
                        text
