使用postgresql-simple查询时出现varchar与Char类型不兼容错误
解决方法
错误根源
问题出在类型匹配错误:
postgresql-simple的query函数会将单字段查询的每行结果封装为Only String类型(这是库用来表示单字段行的专用类型)- 你强行将
query的结果指定为IO (Maybe String),导致库尝试把Only String直接解析成String,触发类型不兼容错误(错误信息里的Char是类型推导混乱后的结果)
修复代码
需要用fromOnly函数提取Only类型中的实际值,修正后的代码有两种写法:
写法一(清晰版)
-- 需先导入:import Database.PostgreSQL.Simple.FromField (fromOnly) maybeUsername <- liftIO $ do -- 查询得到单字段行的列表,类型为 [Only String] rows <- query conn "SELECT username FROM public.\"Users\" WHERE \"userId\" = ?" (Only userId) :: IO [Only String] -- 取第一行(如果存在) let maybeRow = listToMaybe rows -- 从Only中提取String,转换为Maybe String return $ fromOnly <$> maybeRow case maybeUsername of Just username -> liftIO $ putStrLn $ "Username is " ++ username Nothing -> liftIO $ putStrLn $ "Could not find a record for userId " ++ userId
写法二(简洁版)
-- 需先导入:import Database.PostgreSQL.Simple.FromField (fromOnly) maybeUsername <- liftIO $ fmap (fmap fromOnly) $ listToMaybe <$> query conn "SELECT username FROM public.\"Users\" WHERE \"userId\" = ?" (Only userId) :: IO (Maybe String) case maybeUsername of Just username -> liftIO $ putStrLn $ "Username is " ++ username Nothing -> liftIO $ putStrLn $ "Could not find a record for userId " ++ userId
关键注意点
- 必须导入
Database.PostgreSQL.Simple.FromField模块才能使用fromOnly函数 - 单字段查询的返回类型永远是
[Only a],不能直接写成[a],必须通过fromOnly提取值
内容的提问来源于stack exchange,提问作者altern
相关产品推荐
相关产品推荐

