无法在Yesod Email Authentication的apLogin中使用runFormPost

时间:2016-02-25 23:09:16

标签: yesod yesod-forms

我试图为Yesod的电子邮件身份验证插件编写apLogin,并且表单助手正在抛出类型错误。 runFormPost无法读取loginForm。我尝试过几种不同的类型签名组合,但这个错误信息似乎最清楚。好像我有错误的顶级约束,或者我错过了一个。设置它的最佳方法是什么,以便推断出正确的类型?

authEmail :: (YesodAuthEmail m) => AuthPlugin m
authEmail =
    AuthPlugin "email" dispatch login
  where
    login toParent =
        toWidget $ do
            ((_,widget),enctype) <-  runFormPost loginForm
            [whamlet|
                <form method="post" action="@{toParent loginR}">
            |]
    loginForm extra = do
        let emailSettings = FieldSettings {
            fsLabel = SomeMessage Msg.Email,
            fsTooltip = Nothing,
            fsId = Just "email",
            fsName = Just "email",
            fsAttrs = [("autofocus", "")]
        }

        (emailRes, emailView) <- mreq emailField emailSettings Nothing

        let userRes = UserForm <$> emailRes
        let widget = do
            [whamlet|
                #{extra}
                ^{fvInput emailView}
            |]

        return (userRes, widget)

这是错误:

Could not deduce (MonadIO m0) arising from a use of ‘loginForm’
from the context (YesodAuthEmail m)
  bound by the type signature for
             authEmail :: YesodAuthEmail m => AuthPlugin m
  at Yesod/Auth/Email.hs:260:14-47
or from (MonadWidget m1, YesodAuth (HandlerSite m1))
  bound by the inferred type of
           login :: (MonadWidget m1, YesodAuth (HandlerSite m1)) =>
                    (AuthRoute -> Route (HandlerSite m1)) -> m1 ()
  at Yesod/Auth/Email.hs:(270,5)-(275,14)
The type variable ‘m0’ is ambiguous
Note: there are several potential instances:
  instance MonadIO m =>
           MonadIO
             (conduit-1.2.6.1:Data.Conduit.Internal.Conduit.ConduitM i o m)
    -- Defined in ‘conduit-1.2.6.1:Data.Conduit.Internal.Conduit’
  instance MonadIO m =>
           MonadIO (conduit-1.2.6.1:Data.Conduit.Internal.Pipe.Pipe l i o u m)
    -- Defined in ‘conduit-1.2.6.1:Data.Conduit.Internal.Pipe’
  instance MonadIO IO -- Defined in ‘Control.Monad.IO.Class’
  ...plus 18 others
In the first argument of ‘runFormPost’, namely ‘loginForm’
In a stmt of a 'do' block:
  ((_, widget), enctype) <- runFormPost loginForm
In the second argument of ‘($)’, namely
  ‘do { ((_, widget), enctype) <- runFormPost loginForm;
        (do { (asWidgetT . toWidget)
                ((Text.Blaze.Internal.preEscapedText . T.pack)
                   "<form method=\"post\" action=\"");
              (getUrlRenderParams
               >>=
                 (\ urender_ajDM
                    -> (asWidgetT . toWidget)
                         (toHtml (\ u_ajDN -> urender_ajDM u_ajDN ... (toParent loginR)))));
              (asWidgetT . toWidget)
                ((Text.Blaze.Internal.preEscapedText . T.pack)
                   "\"></form>\n") }) }’

使用handlerToWidget更正的代码:

authEmail :: (YesodAuthEmail m) => AuthPlugin m
authEmail =
    AuthPlugin "email" dispatch login
where
    login toParent = do
            ((_,widget),enctype) <- handlerToWidget $ runFormPost loginForm
            [whamlet|
                <form method="post" action="@{toParent loginR}">
            |]
    loginForm extra = do
        let emailSettings = FieldSettings {
            fsLabel = SomeMessage Msg.Email,
            fsTooltip = Nothing,
            fsId = Just "email",
            fsName = Just "email",
            fsAttrs = [("autofocus", "")]
        }

        (emailRes, emailView) <- mreq emailField emailSettings Nothing

        let userRes = UserForm <$> emailRes
        let widget = do
            [whamlet|
                #{extra}
                ^{fvInput emailView}
            |]

        return (userRes, widget)

错误:

    Could not deduce (MonadIO m0) arising from a use of ‘loginForm’
    from the context (YesodAuthEmail m)
      bound by the type signature for
                 authEmail :: YesodAuthEmail m => AuthPlugin m
      at Yesod/Auth/Email.hs:260:14-47
    or from (MonadIO m1,
             MonadBaseControl IO m1,
             exceptions-0.8.2.1:Control.Monad.Catch.MonadThrow m1,
             YesodAuth site)
      bound by the inferred type of
               login :: (MonadIO m1, MonadBaseControl IO m1,
                         exceptions-0.8.2.1:Control.Monad.Catch.MonadThrow m1,
                         YesodAuth site) =>
                        (AuthRoute -> Route site) -> WidgetT site m1 ()
      at Yesod/Auth/Email.hs:(270,5)-(275,14)
    The type variable ‘m0’ is ambiguous
    Note: there are several potential instances:
      instance MonadIO m =>
               MonadIO
                 (conduit-1.2.6.1:Data.Conduit.Internal.Conduit.ConduitM i o m)
        -- Defined in ‘conduit-1.2.6.1:Data.Conduit.Internal.Conduit’
      instance MonadIO m =>
               MonadIO (conduit-1.2.6.1:Data.Conduit.Internal.Pipe.Pipe l i o u m)
        -- Defined in ‘conduit-1.2.6.1:Data.Conduit.Internal.Pipe’
      instance MonadIO IO -- Defined in ‘Control.Monad.IO.Class’
      ...plus 18 others
    In the first argument of ‘runFormPost’, namely ‘loginForm’
    In the second argument of ‘($)’, namely ‘runFormPost loginForm’
    In a stmt of a 'do' block:
      ((_, widget), enctype) <- handlerToWidget $ runFormPost loginForm

没有toWidgetHandler错误:

    Could not deduce (MonadIO m0) arising from a use of ‘loginForm’
    from the context (YesodAuthEmail m)
      bound by the type signature for
                 authEmail :: YesodAuthEmail m => AuthPlugin m
      at Yesod/Auth/Email.hs:260:14-47
    or from (MonadIO m1,
             MonadBaseControl IO m1,
             exceptions-0.8.2.1:Control.Monad.Catch.MonadThrow m1,
             YesodAuth site)
      bound by the inferred type of
               login :: (MonadIO m1, MonadBaseControl IO m1,
                         exceptions-0.8.2.1:Control.Monad.Catch.MonadThrow m1,
                         YesodAuth site) =>
                        (AuthRoute -> Route site) -> WidgetT site m1 ()
      at Yesod/Auth/Email.hs:(271,5)-(275,10)
    The type variable ‘m0’ is ambiguous
    Note: there are several potential instances:
      instance MonadIO m =>
               MonadIO
                 (conduit-1.2.6.1:Data.Conduit.Internal.Conduit.ConduitM i o m)
        -- Defined in ‘conduit-1.2.6.1:Data.Conduit.Internal.Conduit’
      instance MonadIO m =>
               MonadIO (conduit-1.2.6.1:Data.Conduit.Internal.Pipe.Pipe l i o u m)
        -- Defined in ‘conduit-1.2.6.1:Data.Conduit.Internal.Pipe’
      instance MonadIO IO -- Defined in ‘Control.Monad.IO.Class’
      ...plus 18 others
    In the first argument of ‘runFormPost’, namely ‘loginForm’
    In a stmt of a 'do' block:
      ((_, widget), enctype) <- runFormPost loginForm
    In the expression:
      do { ((_, widget), enctype) <- runFormPost loginForm;
           (do { (asWidgetT . toWidget)
                   ((Text.Blaze.Internal.preEscapedText . T.pack)
                      "<form method=\"post\" action=\"");
                 (getUrlRenderParams
                  >>=
                    (\ urender_ajDM
                       -> (asWidgetT . toWidget)
                            (toHtml (\ u_ajDN -> urender_ajDM u_ajDN ... (toParent loginR)))));
                 (asWidgetT . toWidget)
                   ((Text.Blaze.Internal.preEscapedText . T.pack) "\"></form>\n") }) }

1 个答案:

答案 0 :(得分:0)

我不确定,但我认为您的toWidget电话是您的主要问题。此外,您还需要将runFormPost从处理程序升级到窗口小部件,这可以通过handlerToWidget完成。