子站点类型之谜
Mystery of subsite types
在从身份验证插件实现类型 classes 时,我无法弄清楚我的 Foundation.hs
中应该包含哪些类型/它使用 auth 子站点:
我能感觉到我很亲近,但我缺乏理解。我只是想为 login/registration 页面使用不同的布局。
在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
调用。
在类型class定义中Simple.hs:
class (YesodAuth site, PathPiece (AuthSimpleId site)) => YesodAuthSimple site where
type AuthSimpleId site
...
customAuthLayout :: WidgetFor site () -> AuthHandler site Html
...
我粘贴了 customAuthLayout
来自 defaultLayout
来自 Foundation.hs
的定义
这是我从 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 关于子站点类型的非常好的旧博客 post,但我无法理解 GHC 的错误消息。
我怀疑 Simple.hs 中的类型签名有误,或者我在函数定义中遗漏了某些内容。
尝试在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
的类型签名,我们会看到它 returns HandlerFor site (PageContent (Route site))
。在这种情况下,site
实例化为 App
,也就是您在错误消息中看到的 HandlerFor App (PageContent (Route App))
。
同样,您的 customLayout
函数 returns AuthHandler site Html
。 AuthHandler
只是一个类型同义词,它将 site
限制为等同于 HandlerSite m
的类型,这也是 YesodAuth
的一个实例。这也解析为 App
,这就是我们在错误消息中得到 MonadAuthHandler App m
和 m (PageContent (Route App))
的原因。
在从身份验证插件实现类型 classes 时,我无法弄清楚我的 Foundation.hs
中应该包含哪些类型/它使用 auth 子站点:
我能感觉到我很亲近,但我缺乏理解。我只是想为 login/registration 页面使用不同的布局。
在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
调用。
在类型class定义中Simple.hs:
class (YesodAuth site, PathPiece (AuthSimpleId site)) => YesodAuthSimple site where
type AuthSimpleId site
...
customAuthLayout :: WidgetFor site () -> AuthHandler site Html
...
我粘贴了 customAuthLayout
来自 defaultLayout
来自 Foundation.hs
这是我从 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 关于子站点类型的非常好的旧博客 post,但我无法理解 GHC 的错误消息。
我怀疑 Simple.hs 中的类型签名有误,或者我在函数定义中遗漏了某些内容。
尝试在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
的类型签名,我们会看到它 returns HandlerFor site (PageContent (Route site))
。在这种情况下,site
实例化为 App
,也就是您在错误消息中看到的 HandlerFor App (PageContent (Route App))
。
同样,您的 customLayout
函数 returns AuthHandler site Html
。 AuthHandler
只是一个类型同义词,它将 site
限制为等同于 HandlerSite m
的类型,这也是 YesodAuth
的一个实例。这也解析为 App
,这就是我们在错误消息中得到 MonadAuthHandler App m
和 m (PageContent (Route App))
的原因。