haskell - 这个 YesodAuth 实例有什么问题?

标签 haskell yesod

我刚刚从当前的 yesod 脚手架迁移到最新的 yesod-1.6.0yesod-auth-1.6.2

instance YesodAuth App where
    type AuthId App = UserId

    -- ....

    authenticate creds = runDB $ do
        x <- getBy $ UniqueUser $ credsIdent creds
        case x of
            Just (Entity uid _) -> return $ Authenticated uid
            Nothing -> return $ UserError InvalidUsernamePass

在迁移之前,此代码运行良好。但出现以下错误后。

.../src/Foundation.hs:212:26: error:
    • Could not deduce: m ~ HandlerFor site8
      from the context: (MonadHandler m, HandlerSite m ~ App)
        bound by the type signature for:
                   authenticate :: forall (m :: * -> *).
                                   (MonadHandler m, HandlerSite m ~ App) =>
                                   Creds App -> m (AuthenticationResult App)
        at src/Foundation.hs:212:5-16
      ‘m’ is a rigid type variable bound by
        the type signature for:
          authenticate :: forall (m :: * -> *).
                          (MonadHandler m, HandlerSite m ~ App) =>
                          Creds App -> m (AuthenticationResult App)
        at src/Foundation.hs:212:5-16
      Expected type: m (AuthenticationResult App)
        Actual type: HandlerFor site8 (AuthenticationResult App)
    • In the expression:
        runDB
          $ do x <- getBy $ UniqueUser $ credsIdent creds
               case x of
                 Just (Entity uid _) -> return $ Authenticated uid
                 Nothing -> return $ UserError InvalidUsernamePass
      In an equation for ‘authenticate’:
          authenticate creds
            = runDB
                $ do x <- getBy $ UniqueUser $ credsIdent creds
                     case x of
                       Just (Entity uid _) -> return $ Authenticated uid
                       Nothing -> return $ UserError InvalidUsernamePass
      In the instance declaration for ‘YesodAuth App’
    • Relevant bindings include
        authenticate :: Creds App -> m (AuthenticationResult App)
          (bound at src/Foundation.hs:212:5)
    |
212 |     authenticate creds = runDB $ do
    |                          ^^^^^^^^^^...

我不知道为什么它无法通过类型检查。 runDB 在与 yesod-auth 无关的地方运行良好。

编辑:我提取了似乎相关的代码。

class (MonadResource m, MonadLogger m) => MonadHandler m where
    type HandlerSite m
    type SubHandlerSite m
    liftHandler :: HandlerFor (HandlerSite m) a -> m a
    liftSubHandler :: SubHandlerFor (SubHandlerSite m) (HandlerSite m) a -> m a

instance MonadHandler (HandlerFor site) where
    type HandlerSite (HandlerFor site) = site
    type SubHandlerSite (HandlerFor site) = site
    liftHandler = id
    {-# INLINE liftHandler #-}
    liftSubHandler (SubHandlerFor f) = HandlerFor f
    {-# INLINE liftSubHandler #-}

newtype HandlerFor site a = HandlerFor
    { unHandlerFor :: HandlerData site site -> IO a
    }
    deriving Functor

instance MonadHandler (HandlerFor site) where
    type HandlerSite (HandlerFor site) = site
    type SubHandlerSite (HandlerFor site) = site
    liftHandler = id
    {-# INLINE liftHandler #-}
    liftSubHandler (SubHandlerFor f) = HandlerFor f
    {-# INLINE liftSubHandler #-}

有了上面的定义,我想知道下面的定义无法通过类型检查的原因。

problem :: (MonadHandler m, HandlerSite m ~ App) => m ()
problem = (undefined :: HandlerFor App ())

    • Could not deduce: m ~ HandlerFor App
      from the context: (MonadHandler m, HandlerSite m ~ App)
        bound by the type signature for:
                   problem :: forall (m :: * -> *).
                          (MonadHandler m, HandlerSite m ~ App) =>
                          m ()
        at /intero/intero1940cny-TEMP.hs:210:1-52
      ‘m’ is a rigid type variable bound by
        the type signature for:
          problem :: forall (m :: * -> *).
                 (MonadHandler m, HandlerSite m ~ App) =>
                 m ()
        at /intero/intero1940cny-TEMP.hs:210:1-52
      Expected type: m ()
        Actual type: HandlerFor App ()
    • In the expression: (undefined :: HandlerFor App ())
      In an equation for ‘problem’: problem = (undefined :: HandlerFor App ())
    • Relevant bindings include
        problem :: m ()
          (bound at /intero/intero1940cny-TEMP.hs:211:1)

最佳答案

liftHandler . 放在每个 runDB 之前。

关于haskell - 这个 YesodAuth 实例有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49498584/

相关文章:

haskell - 为什么 unsigned int 在 Haskell 中如此罕见?

haskell - 使用 id 参数为处理程序编写 Yesod 测试用例,其中 id 是实体的键

haskell - Yesod/持久一对一查询

haskell - “Template Haskell + C” 错误的解决方法?

haskell - 是什么让 Bytestring "lazy"?

haskell - 如何在 IO 上下文中生成一个函数对其先前结果的重复应用列表

postgresql - Haskell 持久不同步

haskell - 为参数类型实现 Functor

haskell - 如何从 yesod settings.yml 文件中获取值

web-services - Yesod 持久性示例