diff --git a/ditto-lucid.cabal b/ditto-lucid.cabal
--- a/ditto-lucid.cabal
+++ b/ditto-lucid.cabal
@@ -1,5 +1,5 @@
 Name:                ditto-lucid
-Version:             0.2
+Version:             0.3
 Synopsis:            Add support for using lucid with Ditto
 Description:         Ditto is a library for building and validating forms using applicative functors. This package add support for using ditto with lucid.
 License:             BSD3
@@ -25,7 +25,7 @@
   build-depends:
       base >4.5 && <5
     , lucid < 3.0.0
-    , ditto >= 0.2 && <= 0.3
+    , ditto >= 0.3 && <= 0.4
     , text >= 0.11 && < 1.3
     , path-pieces
   hs-source-dirs: src
diff --git a/src/Ditto/Lucid/Named.hs b/src/Ditto/Lucid/Named.hs
--- a/src/Ditto/Lucid/Named.hs
+++ b/src/Ditto/Lucid/Named.hs
@@ -18,7 +18,7 @@
 foldTraverse_ f = traverse_ (fold . f)
 
 inputText
-  :: (Monad m, FormError err, PathPiece text, Applicative f)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
   => (input -> Either err text)
   -> String
   -> text
@@ -27,8 +27,19 @@
   where
   inputField i a = input_ [type_ "text", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a)]
 
+inputTextMReq
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
+  => (input -> Either err text)
+  -> String
+  -> Maybe text
+  -> Form m input err (HtmlT f ()) text
+inputTextMReq getInput name initialValue = G.inputMaybeReq name getInput inputField initialValue
+  where
+  inputField i Nothing = input_ [type_ "text", id_ (encodeFormId i), name_ (encodeFormId i), required_ "required"]
+  inputField i (Just a) = input_ [type_ "text", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a), required_ "required"]
+
 inputPassword
-  :: (Monad m, FormError err, PathPiece text, Applicative f)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
   => (input -> Either err text)
   -> String
   -> text
@@ -38,7 +49,7 @@
   inputField i a = input_ [type_ "password", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a)]
 
 inputSubmit
-  :: (Monad m, FormError err, PathPiece text, Applicative f)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
   => (input -> Either err text)
   -> String
   -> text
@@ -48,7 +59,7 @@
   inputField i a = input_ [type_ "submit", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a)]
 
 inputReset
-  :: (Monad m, FormError err, PathPiece text, Applicative f)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
   => String
   -> text
   -> Form m input err (HtmlT f ()) ()
@@ -57,7 +68,7 @@
   inputField i = input_ [type_ "submit", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece lbl)]
 
 inputHidden
-  :: (Monad m, FormError err, PathPiece text, Applicative f)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
   => (input -> Either err text)
   -> String
   -> text
@@ -67,7 +78,7 @@
   inputField i a = input_ [type_ "hidden", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a)]
 
 inputButton
-  :: (Monad m, FormError err, PathPiece text, Applicative f)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
   => String
   -> text
   -> Form m input err (HtmlT f ()) ()
@@ -76,7 +87,7 @@
   inputField i = input_ [type_ "button", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece lbl)]
 
 textarea
-  :: (Monad m, FormError err, ToHtml text, Monad f)
+  :: (Monad m, FormError err input, ToHtml text, Monad f)
   => (input -> Either err text)
   -> Int -- ^ cols
   -> Int -- ^ rows
@@ -98,7 +109,7 @@
 --
 -- This control may succeed even if the user does not actually select a file to upload. In that case the uploaded name will likely be \"\" and the file contents will be empty as well.
 inputFile
-  :: (Monad m, FormError err, FormInput input, ErrorInputType err ~ input, Applicative f)
+  :: (Monad m, FormError err input, FormInput input, Applicative f)
   => String
   -> Form m input err (HtmlT f ()) (FileType input)
 inputFile name = G.inputFile name fileView
@@ -107,7 +118,7 @@
 
 -- | Create a @\<button type=\"submit\"\>@ element
 buttonSubmit
-  :: (Monad m, FormError err, PathPiece text, ToHtml children, Monad f)
+  :: (Monad m, FormError err input, PathPiece text, ToHtml children, Monad f)
   => (input -> Either err text)
   -> String
   -> text
@@ -121,7 +132,7 @@
 --
 -- This element does not add any data to the form data set.
 buttonReset
-  :: (Monad m, FormError err, Monad f)
+  :: (Monad m, FormError err input, Monad f)
   => String
   -> HtmlT f ()
   -> Form m input err (HtmlT f ()) ()
@@ -133,7 +144,7 @@
 --
 -- This element does not add any data to the form data set.
 button
-  :: (Monad m, FormError err, Monad f)
+  :: (Monad m, FormError err input, Monad f)
   => String
   -> HtmlT f ()
   -> Form m input err (HtmlT f ()) ()
@@ -159,7 +170,7 @@
 arbitraryHtml = view
 
 inputInt
-  :: (Monad m, FormError err, Applicative f)
+  :: (Monad m, FormError err input, Applicative f)
   => (input -> Either err Int)
   -> String
   -> Int
@@ -175,7 +186,7 @@
       ]
 
 inputDouble
-  :: (Monad m, FormError err, Applicative f)
+  :: (Monad m, FormError err input, Applicative f)
   => (input -> Either err Double)
   -> String
   -> Double
@@ -190,7 +201,7 @@
 --
 -- see also 'inputCheckboxes'
 inputCheckbox
-  :: forall err input m f. (Monad m, FormError err, ErrorInputType err ~ input, Applicative f)
+  :: forall err input m f. (Monad m, FormError err input, Applicative f)
   => Bool -- ^ initially checked
   -> String -- ^
   -> Form m input err (HtmlT f ()) Bool
@@ -222,7 +233,7 @@
 -- | Create a group of @\<input type=\"checkbox\"\>@ elements
 --
 inputCheckboxes
-  :: (Functor m, Monad m, FormError err, ErrorInputType err ~ input, FormInput input, ToHtml lbl, Monad f)
+  :: (Functor m, Monad m, FormError err input, FormInput input, ToHtml lbl, Monad f)
   => String
   -> [(a, lbl)] -- ^ value, label, initially checked
   -> (a -> Bool) -- ^ function which indicates if a value should be checked initially
@@ -240,7 +251,7 @@
 
 -- | Create a group of @\<input type=\"radio\"\>@ elements
 inputRadio
-  :: (Functor m, Monad m, FormError err, ErrorInputType err ~ input, FormInput input, Monad f)
+  :: (Functor m, Monad m, FormError err input, FormInput input, Monad f)
   => String
   -> [(a, Html ())] -- ^ value, label, initially checked
   -> (a -> Bool) -- ^ isDefault
@@ -261,7 +272,7 @@
 --
 -- see also: 'selectMultiple'
 select
-  :: (Functor m, Monad m, FormError err, ErrorInputType err ~ input, FormInput input, Monad f)
+  :: (Functor m, Monad m, FormError err input, FormInput input, Monad f)
   => String
   -> [(a, Html ())] -- ^ value, label
   -> (a -> Bool) -- ^ isDefault, must match *exactly one* element in the list of choices
@@ -284,7 +295,7 @@
 --
 -- This creates a @\<select\>@ element which allows more than one item to be selected.
 selectMultiple
-  :: (Functor m, Monad m, FormError err, ErrorInputType err ~ input, FormInput input, Monad f)
+  :: (Functor m, Monad m, FormError err input, FormInput input, Monad f)
   => String
   -> [(a, Html ())] -- ^ value, label, initially checked
   -> (a -> Bool) -- ^ isSelected initially
diff --git a/src/Ditto/Lucid/Unnamed.hs b/src/Ditto/Lucid/Unnamed.hs
--- a/src/Ditto/Lucid/Unnamed.hs
+++ b/src/Ditto/Lucid/Unnamed.hs
@@ -18,64 +18,74 @@
 foldTraverse_ f = traverse_ (fold . f)
 
 inputText
-  :: (Monad m, FormError error, PathPiece text, Applicative f)
-  => (input -> Either error text)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
+  => (input -> Either err text)
   -> text
-  -> Form m input error (HtmlT f ()) text
+  -> Form m input err (HtmlT f ()) text
 inputText getInput initialValue = G.input getInput inputField initialValue
   where
-    inputField i a = input_ [type_ "text", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a)]
+  inputField i a = input_ [type_ "text", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a)]
 
+inputTextMReq
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
+  => (input -> Either err text)
+  -> Maybe text
+  -> Form m input err (HtmlT f ()) text
+inputTextMReq getInput initialValue = G.inputMaybeReq getInput inputField initialValue
+  where
+  inputField i Nothing = input_ [type_ "text", id_ (encodeFormId i), name_ (encodeFormId i), required_ "required"]
+  inputField i (Just a) = input_ [type_ "text", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a), required_ "required"]
+
 inputPassword
-  :: (Monad m, FormError error, PathPiece text, Applicative f)
-  => (input -> Either error text)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
+  => (input -> Either err text)
   -> text
-  -> Form m input error (HtmlT f ()) text
+  -> Form m input err (HtmlT f ()) text
 inputPassword getInput initialValue = G.input getInput inputField initialValue
   where
   inputField i a = input_ [type_ "password", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a)]
 
 inputSubmit
-  :: (Monad m, FormError error, PathPiece text, Applicative f)
-  => (input -> Either error text)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
+  => (input -> Either err text)
   -> text
-  -> Form m input error (HtmlT f ()) (Maybe text)
+  -> Form m input err (HtmlT f ()) (Maybe text)
 inputSubmit getInput initialValue = G.inputMaybe getInput inputField (Just initialValue)
   where
   inputField i a = input_ [type_ "submit", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a)]
 
 inputReset
-  :: (Monad m, FormError error, PathPiece text, Applicative f)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
   => text
-  -> Form m input error (HtmlT f ()) ()
+  -> Form m input err (HtmlT f ()) ()
 inputReset lbl = G.inputNoData inputField
   where
   inputField i = input_ [type_ "submit", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece lbl)]
 
 inputHidden
-  :: (Monad m, FormError error, PathPiece text, Applicative f)
-  => (input -> Either error text)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
+  => (input -> Either err text)
   -> text
-  -> Form m input error (HtmlT f ()) text
+  -> Form m input err (HtmlT f ()) text
 inputHidden getInput initialValue = G.input getInput inputField initialValue
   where
   inputField i a = input_ [type_ "hidden", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a)]
 
 inputButton
-  :: (Monad m, FormError error, PathPiece text, Applicative f)
+  :: (Monad m, FormError err input, PathPiece text, Applicative f)
   => text
-  -> Form m input error (HtmlT f ()) ()
+  -> Form m input err (HtmlT f ()) ()
 inputButton lbl = G.inputNoData inputField
   where
   inputField i = input_ [type_ "button", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece lbl)]
 
 textarea
-  :: (Monad m, FormError error, ToHtml text, Monad f)
-  => (input -> Either error text)
+  :: (Monad m, FormError err input, ToHtml text, Monad f)
+  => (input -> Either err text)
   -> Int -- ^ cols
   -> Int -- ^ rows
   -> text -- ^ initial text
-  -> Form m input error (HtmlT f ()) text
+  -> Form m input err (HtmlT f ()) text
 textarea getInput cols rows initialValue = G.input getInput textareaView initialValue
   where
   textareaView i txt =
@@ -91,19 +101,19 @@
 --
 -- This control may succeed even if the user does not actually select a file to upload. In that case the uploaded name will likely be \"\" and the file contents will be empty as well.
 inputFile
-  :: (Monad m, FormError error, FormInput input, ErrorInputType error ~ input, Applicative f)
-  => Form m input error (HtmlT f ()) (FileType input)
+  :: (Monad m, FormError err input, FormInput input, Applicative f)
+  => Form m input err (HtmlT f ()) (FileType input)
 inputFile = G.inputFile fileView
   where
   fileView i = input_ [type_ "file", id_ (encodeFormId i), name_ (encodeFormId i)]
 
 -- | Create a @\<button type=\"submit\"\>@ element
 buttonSubmit
-  :: (Monad m, FormError error, PathPiece text, ToHtml children, Monad f)
-  => (input -> Either error text)
+  :: (Monad m, FormError err input, PathPiece text, ToHtml children, Monad f)
+  => (input -> Either err text)
   -> text
   -> children
-  -> Form m input error (HtmlT f ()) (Maybe text)
+  -> Form m input err (HtmlT f ()) (Maybe text)
 buttonSubmit getInput text c = G.inputMaybe getInput inputField (Just text)
   where
   inputField i a = button_ [type_ "submit", id_ (encodeFormId i), name_ (encodeFormId i), value_ (toPathPiece a)] $ toHtml c
@@ -112,9 +122,9 @@
 --
 -- This element does not add any data to the form data set.
 buttonReset
-  :: (Monad m, FormError error, ToHtml children, Monad f)
+  :: (Monad m, FormError err input, ToHtml children, Monad f)
   => children
-  -> Form m input error (HtmlT f ()) ()
+  -> Form m input err (HtmlT f ()) ()
 buttonReset c = G.inputNoData inputField 
   where
   inputField i = button_ [type_ "reset", id_ (encodeFormId i), name_ (encodeFormId i)] $ toHtml c
@@ -123,9 +133,9 @@
 --
 -- This element does not add any data to the form data set.
 button
-  :: (Monad m, FormError error, ToHtml children, Monad f)
+  :: (Monad m, FormError err input, ToHtml children, Monad f)
   => children
-  -> Form m input error (HtmlT f ()) ()
+  -> Form m input err (HtmlT f ()) ()
 button c = G.inputNoData inputField
   where
   inputField i = button_ [type_ "button", id_ (encodeFormId i), name_ (encodeFormId i)] $ toHtml c
@@ -138,12 +148,12 @@
 label
   :: (Monad m, Monad f)
   => HtmlT f ()
-  -> Form m input error (HtmlT f ()) ()
+  -> Form m input err (HtmlT f ()) ()
 label c = G.label mkLabel
   where
   mkLabel i = label_ [for_ (encodeFormId i)] c
 
-arbitraryHtml :: Monad m => view -> Form m input error view ()
+arbitraryHtml :: Monad m => view -> Form m input err view ()
 arbitraryHtml wrap =
   Form $ do
     id' <- getFormId
@@ -158,7 +168,7 @@
       )
 
 inputInt
-  :: (Monad m, FormError err, Applicative f)
+  :: (Monad m, FormError err input, Applicative f)
   => (input -> Either err Int)
   -> Int
   -> Form m input err (HtmlT f ()) Int
@@ -173,7 +183,7 @@
       ]
 
 inputDouble
-  :: (Monad m, FormError err, Applicative f)
+  :: (Monad m, FormError err input, Applicative f)
   => (input -> Either err Double)
   -> Double
   -> Form m input err (HtmlT f ()) Double
@@ -187,9 +197,9 @@
 --
 -- see also 'inputCheckboxes'
 inputCheckbox
-  :: forall error input m f. (Monad m, FormError error, ErrorInputType error ~ input, Applicative f)
+  :: forall err input m f. (Monad m, FormError err input, Applicative f)
   => Bool -- ^ initially checked
-  -> Form m input error (HtmlT f ()) Bool
+  -> Form m input err (HtmlT f ()) Bool
 inputCheckbox initiallyChecked =
   Form $ do
     i <- getFormId
@@ -218,10 +228,10 @@
 -- | Create a group of @\<input type=\"checkbox\"\>@ elements
 --
 inputCheckboxes
-  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, Monad f)
+  :: (Functor m, Monad m, FormError err input, FormInput input, Monad f)
   => [(a, Html ())] -- ^ value, label, initially checked
   -> (a -> Bool) -- ^ function which indicates if a value should be checked initially
-  -> Form m input error (HtmlT f ()) [a]
+  -> Form m input err (HtmlT f ()) [a]
 inputCheckboxes choices isChecked =
   G.inputMulti choices mkCheckboxes isChecked
   where
@@ -237,10 +247,10 @@
 
 -- | Create a group of @\<input type=\"radio\"\>@ elements
 inputRadio
-  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, Monad f)
+  :: (Functor m, Monad m, FormError err input, FormInput input, Monad f)
   => [(a, Html ())] -- ^ value, label, initially checked
   -> (a -> Bool) -- ^ isDefault
-  -> Form m input error (HtmlT f ()) a
+  -> Form m input err (HtmlT f ()) a
 inputRadio choices isDefault =
   G.inputChoice isDefault choices mkRadios
   where
@@ -257,10 +267,10 @@
 --
 -- see also: 'selectMultiple'
 select
-  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, Monad f)
+  :: (Functor m, Monad m, FormError err input, FormInput input, Monad f)
   => [(a, Html ())] -- ^ value, label
   -> (a -> Bool) -- ^ isDefault, must match *exactly one* element in the list of choices
-  -> Form m input error (HtmlT f ()) a
+  -> Form m input err (HtmlT f ()) a
 select choices isDefault =
   G.inputChoice isDefault choices mkSelect
   where
@@ -280,10 +290,10 @@
 --
 -- This creates a @\<select\>@ element which allows more than one item to be selected.
 selectMultiple
-  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, Monad f)
+  :: (Functor m, Monad m, FormError err input, FormInput input, Monad f)
   => [(a, Html ())] -- ^ value, label, initially checked
   -> (a -> Bool) -- ^ isSelected initially
-  -> Form m input error (HtmlT f ()) [a]
+  -> Form m input err (HtmlT f ()) [a]
 selectMultiple choices isSelected =
   G.inputMulti choices mkSelect isSelected
   where
