使用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
相关产品推荐
相关产品推荐

