You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

getAuthEntity报错‘Couldn’t match expected type’,Yesod硬编码认证求助

Fixing the getAuthEntity Type Mismatch in Yesod Hardcoded Authentication

Let's break down why you're hitting that type error and how to fix it. The core issue here is how you've defined your AuthId type and how getAuthEntity needs to handle it.

First: Clarify Your Authentication Strategy

Your AuthId App = Either UserId Text suggests you're trying to mix database-backed users (UserId) and hardcoded users (Text usernames). That's totally valid, but you need to explicitly handle both cases in getAuthEntity—which is likely where your type mismatch is coming from.

If you only need hardcoded authentication (no database users), simplify your AuthId to just Text instead of Either—this will eliminate a lot of complexity.

Step 1: Fix the YesodAuth Instance

Here's a complete, corrected YesodAuth instance that handles both database and hardcoded users (adjust to your actual User model):

instance YesodAuth App where
    type AuthId App = Either UserId Text

    -- Login/logout destinations (keep your existing values)
    loginDest _ = HomeR
    logoutDest _ = HomeR

    -- Handle authentication for both hardcoded and DB users
    authenticate creds = do
        -- First check for hardcoded users
        mHardcodedUser <- getUserHardcoded (credsIdent creds)
        case mHardcodedUser of
            Just _ -> return $ Authenticated (Right (credsIdent creds))
            Nothing -> do
                -- Fall back to database authentication if needed
                mDbUser <- runDB $ getBy $ UniqueUserName (credsIdent creds)
                case mDbUser of
                    Just (Entity uid _) -> return $ Authenticated (Left uid)
                    Nothing -> return $ UserError InvalidLogin

    -- Resolve AuthId to a database Entity (or hardcoded user Entity)
    getAuthEntity authId = case authId of
        -- Handle database users: fetch by UserId
        Left uid -> runDB $ get uid >>= \case
            Just user -> return $ Just (Entity uid user)
            Nothing -> return Nothing
        -- Handle hardcoded users: either fetch from DB (if you mirrored them) or return a virtual Entity
        Right username -> do
            mHardcodedUser <- getUserHardcoded username
            case mHardcodedUser of
                Just user -> do
                    -- If you keep hardcoded users in the DB, fetch them by username
                    mDbUser <- runDB $ getBy $ UniqueUserName username
                    return mDbUser
                Nothing -> return Nothing

Step 2: Ensure You Implemented YesodAuthHardcoded

Don't forget the required instance for hardcoded auth—this is where you define valid users and passwords:

instance YesodAuthHardcoded App where
    validatePasswordHardcoded username password = return $
        (username == "admin" && password == "supersecret123") ||
        (username == "guest" && password == "guestpass")

    getUserHardcoded username = return $ case username of
        "admin" -> Just User { userName = "admin", userEmail = "admin@yourdomain.com" }
        "guest" -> Just User { userName = "guest", userEmail = "guest@yourdomain.com" }
        _ -> Nothing

Why You Got the Type Error

The getAuthEntity function expects to take your AuthId type and return a Maybe (Entity user). If you didn't handle the Either UserId Text case—for example, trying to directly pass an Either to runDB get—Haskell couldn't match the expected UserId type with your Either type, hence the "Couldn’t match expected type" error.

Simplification for Pure Hardcoded Auth

If you don't need database users at all, simplify your AuthId to Text and adjust getAuthEntity like this:

instance YesodAuth App where
    type AuthId App = Text

    loginDest _ = HomeR
    logoutDest _ = HomeR

    authenticate creds = do
        isValid <- validatePasswordHardcoded (credsIdent creds) (credsPassword creds)
        if isValid
            then return $ Authenticated (credsIdent creds)
            else return $ UserError InvalidLogin

    getAuthEntity username = getUserHardcoded username >>= \case
        Just user -> return $ Just (Entity (toSqlKey 0) user) -- Use a dummy key if no DB
        Nothing -> return Nothing

内容的提问来源于stack exchange,提问作者Marc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:34:02