I am trying to create bootstrap 3 compatibility for Yesod. However, it is not possible to do this using the "renderBootstrap3" function, because you cannot add a class to the inputs. So, I chose to create bootable versions of fields in Form.Fields
. The idea is that I can clone normal fields, but add a class declaration to the attribute array. Here is the relevant code:
import qualified Yesod.Form.Fields as F injectClass :: (Text -> Text -> [(Text,Text)] -> Either Text a -> Bool -> WidgetT (HandlerSite m) IO () Text -> Text -> [(Text,Text)] -> Either Text a -> Bool -> WidgetT (HandlerSite m) IO () injectClass fab attrs de = fab attrs de textField :: (Monad m, RenderMessage (HandlerSite m) FormMessage) => Field m Text textField = addInputClass F.textField addInputClass :: (Monad m, RenderMessage (HandlerSite m) FormMessage) => Field ma -> Field ma addInputClass f = f { fieldView = (injectClass $ fieldView f)}
So, I intend to accept the normal version of the text field and use the write syntax to change only the fieldView method. This method should be replaced with one that is identical, except for adding a class attribute. This is not yet implemented in the code above. It probably looks something like this:
injectClass fab attrs de = fab (("class", "form-control") : attrs) de
In any case, the problem is that the source code will not compile. I get an equality constraint error:
Could not deduce (HandlerSite m0 ~ HandlerSite m) from the context (Monad m, RenderMessage (HandlerSite m) FormMessage) bound by the type signature for addInputClass :: (Monad m, RenderMessage (HandlerSite m) FormMessage) => Field ma -> Field ma at Field/Bootstrap.hs:27:18-95 NB: `HandlerSite' is a type function, and may not be injective The type variable `m0' is ambiguous Possible fix: add a type signature that fixes these type variable(s) Expected type: FieldViewFunc ma Actual type: Text -> Text -> [(Text, Text)] -> Either Text a -> Bool -> WidgetT (HandlerSite m0) IO () In the `fieldView' field of a record In the expression: f {fieldView = (injectClass $ fieldView f)} In an equation for `addInputClass': addInputClass f = f {fieldView = (injectClass $ fieldView f)}
Note that FieldViewFunc ma
is defined as
type FieldViewFunc ma = Text -- ^ ID -> Text -- ^ Name -> [(Text, Text)] -- ^ Attributes -> Either Text a -- ^ Either (invalid text) or (legitimate result) -> Bool -- ^ Required? -> WidgetT (HandlerSite m) IO ()
So I'm not far off. The problem (I think) is that it does not confirm that injectClass
does not change the monad. However, this should be obvious to the compiler. The typical signature for injectClass
is clear. I am looking for what I need to do to satisfy the GHC. Thanks for any help, and let me know if I can be more clear.