diff --git a/digestive-functors.cabal b/digestive-functors.cabal
--- a/digestive-functors.cabal
+++ b/digestive-functors.cabal
@@ -1,5 +1,5 @@
 Name:     digestive-functors
-Version:  0.4.0.0
+Version:  0.4.1.0
 Synopsis: A practical formlet library
 
 Description:
@@ -46,23 +46,24 @@
   Ghc-options:    -Wall -fwarn-tabs
 
   Exposed-modules:     
-    Text.Digestive,
-    Text.Digestive.Form,
-    Text.Digestive.Form.Encoding,
-    Text.Digestive.Types,
-    Text.Digestive.View,
+    Text.Digestive
+    Text.Digestive.Form
+    Text.Digestive.Form.Encoding
+    Text.Digestive.Ref
+    Text.Digestive.Types
     Text.Digestive.Util
+    Text.Digestive.View
 
   Other-modules:
-    Text.Digestive.Field,
+    Text.Digestive.Field
     Text.Digestive.Form.Internal
 
   Build-depends:
     base       >= 4       && < 5,
-    bytestring >= 0.9,
-    containers >= 0.3,
+    bytestring >= 0.9     && < 0.10,
+    containers >= 0.3     && < 0.6,
     mtl        >= 1.1.0.0 && < 3,
-    text       >= 0.10
+    text       >= 0.10    && < 0.12
 
 Test-suite digestive-functors-tests
   Type:           exitcode-stdio-1.0
@@ -76,10 +77,10 @@
     test-framework-hunit >= 0.2 && < 0.3,
     -- Copied from regular dependencies:
     base       >= 4       && < 5,
-    bytestring >= 0.9,
-    containers >= 0.3,
+    bytestring >= 0.9     && < 0.10,
+    containers >= 0.3     && < 0.6,
     mtl        >= 1.1.0.0 && < 3,
-    text       >= 0.10
+    text       >= 0.10    && < 0.12
 
 Source-repository head
   Type:     git
diff --git a/src/Text/Digestive.hs b/src/Text/Digestive.hs
--- a/src/Text/Digestive.hs
+++ b/src/Text/Digestive.hs
@@ -3,11 +3,13 @@
 module Text.Digestive
     ( module Text.Digestive.Form
     , module Text.Digestive.Form.Encoding
+    , module Text.Digestive.Ref
     , module Text.Digestive.Types
     , module Text.Digestive.View
     ) where
 
-import Text.Digestive.Form
-import Text.Digestive.Form.Encoding
-import Text.Digestive.Types
-import Text.Digestive.View
+import           Text.Digestive.Form
+import           Text.Digestive.Form.Encoding
+import           Text.Digestive.Ref
+import           Text.Digestive.Types
+import           Text.Digestive.View
diff --git a/src/Text/Digestive/Field.hs b/src/Text/Digestive/Field.hs
--- a/src/Text/Digestive/Field.hs
+++ b/src/Text/Digestive/Field.hs
@@ -19,7 +19,7 @@
 data Field v a where
     Singleton :: a -> Field v a
     Text      :: Text -> Field v Text
-    Choice    :: Eq a => [(a, v)] -> Int -> Field v a
+    Choice    :: [(a, v)] -> Int -> Field v (a, Int)
     Bool      :: Bool -> Field v Bool
     File      :: Field v (Maybe FilePath)
 
@@ -39,12 +39,13 @@
 evalField _    _                 (Singleton x) = x
 evalField _    (TextInput x : _) (Text _)      = x
 evalField _    _                 (Text x)      = x
-evalField _    (TextInput x : _) (Choice ls y) = fromMaybe (fst $ ls !! y) $ do
-    -- Expects input in the form of @foo.bar.2@
-    t <- listToMaybe $ reverse $ toPath x
-    i <- readMaybe $ T.unpack t
-    return $ fst $ ls !! i
-evalField _    _                 (Choice ls x) = fst $ ls !! x
+evalField _    (TextInput x : _) (Choice ls y) =
+    fromMaybe (fst (ls !! y), y) $ do
+        -- Expects input in the form of @foo.bar.2@
+        t <- listToMaybe $ reverse $ toPath x
+        i <- readMaybe $ T.unpack t
+        return $ (fst (ls !! i), i)
+evalField _    _                 (Choice ls x) = (fst (ls !! x), x)
 evalField Get  _                 (Bool x)      = x
 evalField Post (TextInput x : _) (Bool _)      = x == "on"
 evalField Post _                 (Bool _)      = False
diff --git a/src/Text/Digestive/Form.hs b/src/Text/Digestive/Form.hs
--- a/src/Text/Digestive/Form.hs
+++ b/src/Text/Digestive/Form.hs
@@ -10,6 +10,7 @@
     , string
     , stringRead
     , choice
+    , choice'
     , bool
     , file
 
@@ -51,9 +52,14 @@
 stringRead :: (Monad m, Read a, Show a) => v -> Formlet v m a
 stringRead err = transform (readTransform err) . string . fmap show
 
-choice :: Eq a => [(a, v)] -> Formlet v m a
-choice items def = Pure Nothing $ Choice items $ fromMaybe 0 $
+choice :: (Eq a, Monad m) => [(a, v)] -> Formlet v m a
+choice items def = choice' items $
     maybe Nothing (\d -> findIndex ((== d) . fst) items) def
+
+-- | Sometimes there is no good 'Eq' instance for 'choice'. In this case, you
+-- can use this function, which takes an index in the list as default.
+choice' :: Monad m => [(a, v)] -> Maybe Int -> Form v m a
+choice' items def = fmap fst $ Pure Nothing $ Choice items $ fromMaybe 0 def
 
 bool :: Formlet v m Bool
 bool = Pure Nothing . Bool . fromMaybe False
diff --git a/src/Text/Digestive/Form/Internal.hs b/src/Text/Digestive/Form/Internal.hs
--- a/src/Text/Digestive/Form/Internal.hs
+++ b/src/Text/Digestive/Form/Internal.hs
@@ -12,6 +12,7 @@
     , toFormTree
     , children
     , (.:)
+    , getRef
     , lookupForm
     , toField
     , queryField
diff --git a/src/Text/Digestive/Ref.hs b/src/Text/Digestive/Ref.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Digestive/Ref.hs
@@ -0,0 +1,31 @@
+--------------------------------------------------------------------------------
+-- | This module contains utilities for creating text fragments to identify
+-- forms.
+{-# LANGUAGE OverloadedStrings #-}
+module Text.Digestive.Ref
+    ( makeRef
+    , makeRefs
+    ) where
+
+
+--------------------------------------------------------------------------------
+import qualified Data.ByteString    as B
+import           Data.Text          (Text)
+import qualified Data.Text          as T
+import qualified Data.Text.Encoding as T
+import           Text.Printf        (printf)
+
+
+--------------------------------------------------------------------------------
+-- | Convert an arbitrary text value (possibly containing spaces, dots etc. to
+-- a text value that safely be used as an identifier in forms.
+makeRef :: Text -> Text
+makeRef =
+    -- We simply UTF-8 encode and then hex encode, so all characters are valid.
+    T.append "df-" . T.pack . (printf "%02x" =<<) . B.unpack . T.encodeUtf8
+
+
+--------------------------------------------------------------------------------
+-- | Create an infinite list of refs.
+makeRefs :: [Text]
+makeRefs = ["df-" `T.append` T.pack (show i) | i <- [0 :: Int ..]]
diff --git a/src/Text/Digestive/View.hs b/src/Text/Digestive/View.hs
--- a/src/Text/Digestive/View.hs
+++ b/src/Text/Digestive/View.hs
@@ -9,6 +9,7 @@
 
       -- * Operations on views
     , subView
+    , subViews
 
       -- * Querying a view
       -- ** Low-level
@@ -31,8 +32,7 @@
 
 import Control.Arrow (second)
 import Control.Monad.Identity (Identity)
-import Data.List (findIndex, isPrefixOf)
-import Data.Maybe (fromMaybe)
+import Data.List (isPrefixOf)
 
 import Data.Text (Text)
 import qualified Data.Text as T
@@ -80,6 +80,15 @@
   where
     path = toPath ref
 
+-- | Returns all immediate subviews of a view
+subViews :: View v -> [View v]
+subViews view@(View _ _ form _ _ _) =
+    [subView r view | r <- go (SomeForm form)]
+  where
+    go (SomeForm f) = case getRef f of
+        Nothing -> [r | c <- children f, r <- go c]
+        Just r  -> [r]
+
 -- | Determine an absolute 'Path' for a field in the form
 absolutePath :: Text -> View v -> Path
 absolutePath ref view@(View name _ _ _ _ _) = name : viewPath ref view
@@ -123,8 +132,7 @@
     eval' :: Field v b -> ([v], Int)
     eval' field = case field of
         Choice xs i ->
-            let x   = evalField method givenInput (Choice xs i)
-                idx = fromMaybe 0 $ findIndex (== x) (map fst xs)
+            let idx = snd $ evalField method givenInput (Choice xs i)
             in (map snd xs, idx)
         f           -> error $ T.unpack ref ++ ": expected (Choice _ _), " ++
             "but got: (" ++ show f ++ ")"
