0

我正在尝试为 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") }) }
4

1 回答 1

0

我不确定,但我认为你的toWidget电话是你的主要问题。此外,您需要将您的runFormPost从 Handler 提升到 Widget,这可以通过handlerToWidget.

于 2016-02-26T06:09:38.880 回答