getAuthEntity报错‘Couldn’t match expected type’,Yesod硬编码认证求助
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

