此帖子的第一个标题是:升级到Yesod-auth-1.6:无法将类型“ Auth”与“ App”匹配-类型相等SubHandlerSite m ~ Auth
在升级到Yesod-1.6时,我正在为新类型而苦苦挣扎。
instance YesodAuth App where
type AuthId App = UserFId
-- etc.
instance YesodAuthEmail App where
type AuthEmailId App = UserFId
-- etc.
getSessionUser :: HandlerFor App User
getSessionUser = do
mu <- maybeAuthId -- UserFId is both an instance of 'AuthId App' and 'AuthEmailId App'
case mu of
Nothing -> redirect HomeR
Just u -> fromString . T.unpack . fromJust <$> getEmail u
和编译错误:
• Couldn't match type ‘Auth’ with ‘App’
arising from a use of ‘getEmail’
• In the second argument of ‘(<$>)’, namely ‘(getEmail u)’
In the expression: fromString . unpack . fromJust <$> getEmail u
In a case alternative:
Just u -> fromString . unpack . fromJust <$> getEmail u
实际上,getEmail
的类型签名为:
getEmail :: (YesodAuthEmail (HandlerSite m), MonadHandler m,
MonadUnliftIO m, SubHandlerSite m ~ Auth) =>
AuthEmailId (HandlerSite m) -> m (Maybe Email)
(ghci)> :t fromJust <$> maybeAuthId >>= getEmail
fromJust <$> maybeAuthId >>= getEmail
:: (YesodAuthEmail (HandlerSite m), MonadHandler m,
MonadUnliftIO m,
AuthId (HandlerSite m) ~ AuthEmailId (HandlerSite m),
SubHandlerSite m ~ Auth) =>
m (Maybe Email)
我假设我需要解决类型相等约束SubHandlerSite m ~ Auth
,但是我不知道该怎么做。
编辑: 好的,我退后一步,然后深入研究yesod的文档,以寻找解决我的问题的可能方法。我找不到合适的解决方案。也许我正在尝试解决错误的问题?
实际上,我的函数getSessionUser
是Handler a
。
我想在getEmail
中致电getSessionUser
。 getEmail
是AuthHandler
的功能。
此外,ghci推断出的类型签名使我感到困惑:
getEmail :: (YesodAuthEmail (HandlerSite m), MonadHandler m, MonadUnliftIO m, SubHandlerSite m ~ Auth) => AuthEmailId (HandlerSite m) -> m (Maybe Email)
而文档提供了这种类型签名:
getEmail :: AuthEmailId site -> AuthHandler site (Maybe Email)
我的理解(请告诉我我是否错)是无法组合AuthHandler
函数和Handler
函数。
因此,我想出了一个更简单的解决方案,即直接从函数getSessionUser
中读取数据库。实际上,getEmail
将在内部访问数据库,因此最终结果是相同的:
getSessionUser :: Handler User
getSessionUser = do
mu <- maybeAuthId
case mu of
-- redirect to the home page if we are not authenticated.
Nothing -> redirect HomeR
Just u -> liftHandler $ runDB $
textToUser . userFEmail . fromJust <$> get u