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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 17:42:40