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

使用postgresql-simple执行SQL查询报错:No instance for (FromRow Int)

问题

用户使用postgresql-simple库执行SQL查询的Haskell代码如下:

{-# LANGUAGE OverloadedStrings #-}
module Main where

import           Database.PostgreSQL.Simple

main :: IO ()
main = do
  putStrLn "Hello, Haskell!"

f :: Connection -> IO ()
f conn = do
  xs <- query conn "selct 123" ()
  print (xs :: [Int])

运行时出现错误:

src/Main.hs:12:9-33: error:
    • No instance for (FromRow Int) arising from a use of ‘query’
    • In a stmt of a 'do' block: xs <- query conn "selct 123" ()
      In the expression:
        do xs <- query conn "selct 123" ()
           print (xs :: [Int])
      In an equation for ‘f’:
          f conn
            = do xs <- query conn "selct 123" ()
                 print (xs :: [Int])
解决方案

需要解决两个核心问题:

  • 修复SQL拼写错误:将语句中的selct修正为正确的select。
  • 适配行映射规则:postgresql-simple的query函数返回行的列表,单个数值属于「一行一列」的结果,Int本身没有FromRow实例(FromRow用于映射整行数据),需要用库提供的Only Int类型来包装单列表结果,它已实现对应的FromRow实例。

修正后的代码示例

{-# LANGUAGE OverloadedStrings #-}
module Main where

import           Database.PostgreSQL.Simple
import           Database.PostgreSQL.Simple.FromRow (Only(..))

main :: IO ()
main = do
  putStrLn "Hello, Haskell!"

f :: Connection -> IO ()
f conn = do
  -- 修正SQL拼写,用Only接收单列表行结果
  rows <- query conn "select 123" ()
  -- 从每个行包装器中提取Int值
  let values = map fromOnly rows :: [Int]
  print values

如果只需要单个结果,也可以直接提取首行:

f :: Connection -> IO ()
f conn = do
  Only value <- head <$> query conn "select 123" ()
  print (value :: Int)

补充说明

postgresql-simple中FromRow类型类负责将数据库行转换为Haskell类型。当查询结果是单个值时,数据库返回的是包含一列的行,Only a是库专门设计的单列表包装类型,它实现了FromRow,因此能被query正确解析。fromOnly函数用于从Only包装器中取出实际的数值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 00:22:18