Search code examples
haskellyesodyesod-forms

Yesod fvInput can't match 'App' with 'Auth'


I'm trying to write a custom Yesod registration form. The problem I'm having is that when it gets to fvInput it seems like it's using App instead of Auth. I'm not quite sure how this should be handled and I can't seem to find the terminology for it. I've tried lifting in various ways within the form and I can only get it to throw different errors. Also, the only time this error is thrown is if I have the fvInput line, but if I remove that no error is thrown and it compiles correctly.

Code:

registrationForm :: Html -> MForm (HandlerT Auth (HandlerT App IO)) (FormResult UserForm, Widget)
registrationForm extra = do
    (emailRes, emailView) <- mreq textField "" Nothing
    let userRes = UserForm <$> emailRes
    let widget = do
        [whamlet|
            #{extra}
            ^{fvInput emailView}
            <input type=Submit value="Registration">
        |]

    return (userRes, widget)

Error:

Foundation.hs:169:30:
    Couldn't match type ‘App’ with ‘Auth’
    In the second argument of ‘(GHC.Base..)’, namely ‘toWidget’
    In the expression: asWidgetT GHC.Base.. toWidget
    In a stmt of a 'do' block:
      (asWidgetT GHC.Base.. toWidget) (fvInput emailView)

Thank you in advance for any help!

  • Edit

Error with a lift before the mreq:

Foundation.hs:166:49:
   Couldn't match type ‘HandlerT Auth (HandlerT App IO)’
               with ‘transformers-0.4.2.0:Control.Monad.Trans.RWS.Lazy.RWST
                       (Maybe (Env, FileEnv), HandlerSite m0, [Lang]) Enctype Ints m0’
    Expected type: HandlerT
                 Auth (HandlerT App IO) (FormResult Text, FieldView App)
      Actual type: MForm m0 (FormResult Text, FieldView App)
    In the second argument of ‘($)’, namely ‘mreq textField "" Nothing’
    In a stmt of a 'do' block:
      (emailRes, emailView) <- lift $ mreq textField "" Nothing

Solution

  • Your returned Widget type is actually:

    WidgetT App IO ()
    

    Thus there's a mismatch between the Widget (which lives in just App) and the emailView (which lives in the lifted HandlerT Auth (HandlerT App IO) monad).

    To solve this problem:

    1. Change you type signature to registrationForm :: Html -> MForm (HandlerT App IO) (FormResult UserForm, Widget)
    2. At the usage site, you'll need to employ a lift most likely, but after you've already called the appropriate run function for the form