【问题标题】:Mystery of subsite types子站点类型之谜
【发布时间】:2020-02-23 18:19:21
【问题描述】:

从身份验证插件实现类型类时,我无法弄清楚我的Foundation.hs 中应该包含哪些类型/它使用了身份验证子站点:

我能感觉到我很接近,但我缺乏理解。我只是想为登录/注册页面使用不同的布局。

在 Foundation.hs 中:


instance YesodAuthSimple App where
    type AuthSimpleId App = UserId

    ...

    -- Works
    onRegisterSuccess :: YesodAuthSimple site => AuthHandler site Html
    onRegisterSuccess = authLayout $ [whamlet|
      $newline never
      <div>
        <h1>You Registered successfully.
        <p>
          Some text here.
    |]  

    -- Works when I do not write a type signature
    loginTemplate toParent mErr = $(widgetFile "authpartials/login")


    -- Does not work with or without type signatures
    customAuthLayout widget = do 
        master <- getYesod
        mmsg <- getMessage
        muser <- maybeAuthPair
        mcurrentRoute <- getCurrentRoute
        pc <- widgetToPageContent $ do
            $(widgetFile "custom-auth-layout")
        withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")

432:15 指的是widgetToPageContent 调用。

在类型类定义Simple.hs中:

class (YesodAuth site, PathPiece (AuthSimpleId site)) => YesodAuthSimple site where
  type AuthSimpleId site

  ...

  customAuthLayout :: WidgetFor site () -> AuthHandler site Html

  ...

我从 Foundation.hs 中的 defaultLayout 粘贴了 customAuthLayout 的定义

这是我从 GHC 得到的错误:

Foundation.hs:432:15: error:
    • Could not deduce: m ~ HandlerFor App
      from the context: MonadAuthHandler App m
        bound by the type signature for:
                   customAuthLayout :: WidgetFor App () -> AuthHandler App Html
        at src/Foundation.hs:(427,5)-(434,79)
      ‘m’ is a rigid type variable bound by
        the type signature for:
          customAuthLayout :: WidgetFor App () -> AuthHandler App Html
        at src/Foundation.hs:(427,5)-(434,79)
      Expected type: m (PageContent (Route App))
        Actual type: HandlerFor App (PageContent (Route App))
    • In a stmt of a 'do' block:
        pc <- widgetToPageContent
                $ do (do do (asWidgetT GHC.Base.. toWidget)
                              ((blaze-markup-0.8.2.2:Text.Blaze.Internal.preEscapedText
                                  GHC.Base.. Data.Text.pack)
                                 "<!--  custom-auth-layout -->
<body class="d-flex align-items-center bg-auth border-top border-top-2 border-primary">")
                            ....)
      In the expression:
        do master <- getYesod
           mmsg <- getMessage
           muser <- maybeAuthPair
           mcurrentRoute <- getCurrentRoute
           ....
      In an equation for ‘customAuthLayout’:
          customAuthLayout widget
            = do master <- getYesod
                 mmsg <- getMessage
                 muser <- maybeAuthPair
                 ....
    |
432 |         pc <- widgetToPageContent $ do
    |               ^^^^^^^^^^^^^^^^^^^^^^^^...


我已经成功地将本教程用于普通(非子站点页面)https://ersocon.net/cookbooks/yesod/html-and-seo/custom-layouts

但我被子网站类型绊倒了。我已阅读 Michael Snoyman 关于子站点类型的非常好的旧博客文章,但我无法理解 GHC 的错误消息。

我怀疑 Simple.hs 中的类型签名有误,或者我在函数定义中遗漏了某些内容。

【问题讨论】:

    标签: haskell yesod template-haskell


    【解决方案1】:

    尝试在widgetToPageContent之前添加liftHandler

    ...
    pc <- liftHandler $ widgetToPageContent $ do
        $(widgetFile "custom-auth-layout")
    ...
    

    错误消息中的关键行是:

      Could not deduce: m ~ HandlerFor App
      ...
      Expected type: m (PageContent (Route App))
        Actual type: HandlerFor App (PageContent (Route App))
    

    它基本上告诉我们它期望一个更通用的类型m,但它却得到了一个HandlerFor App。所以解决方案就是解除使用liftHandler函数调用widgetToPageContent

    更详细地说,如果我们查看函数widgetToPageContent 的类型签名,我们会看到它返回HandlerFor site (PageContent (Route site))。在这种情况下,site 实例化为 App,这就是您在错误消息中看到的 HandlerFor App (PageContent (Route App))

    同样,您的customLayout 函数返回AuthHandler site HtmlAuthHandler 只是一个类型同义词,它将site 限制为等价于HandlerSite m 的类型,HandlerSite m 也是YesodAuth 的一个实例。这也解析为App,这就是我们在错误消息中得到MonadAuthHandler App mm (PageContent (Route App)) 的原因。

    【讨论】:

    • 这是一个很棒而详细的答案,这很有效,谢谢@alexandre-lucchesi
    • 没问题!很高兴它有帮助。 :)
    猜你喜欢
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    • 2012-11-29
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多