为什么 Haskell 不能将 PosgreSQL 字符串分成字段?
我是 PostgreSQL 的新手。简单,所以如果问题很愚蠢,请原谅。
我正在阅读本教程: Postgresql 数据访问使用 Haskell
我得到了第一个可以运行的演示程序。
现在我正在使用这个函数:
retrieveClient :: Connection -> Int -> IO [Only String]
retrieveClient conn cid = query conn "SELECT ticker FROM spot_daily WHERE id = ?" $ (Only cid)
并希望修改它以返回 IO [(String, Integer, Float)] 。
所以我写道:
retrieveClient2 :: Connection -> Float -> IO [(String, Integer, Float)]
retrieveClient2 conn cid = query conn "SELECT (ticker, timestamp, some_val) FROM spot_daily WHERE p_open > ?" $ (Only cid)
main :: IO ()
main = do
conn <- connect localPG
mapM_ print =<< (retrieveClient2 conn 50.0)
我明白了:
MyApp-exe.EXE: Incompatible {errSQLType = "record", errSQLTableOid = Nothing, errSQLField = "row", errHaskellType = "Text", errMessage = "types incompatible"}
在 Haskell 世界里,“在 Hackage 上搜索你想要的类型签名!”是很常见的说法。但从错误消息中我不清楚什么类型的签名会让 GHC 满意。
有没有这样的转换函数?我尝试这样做:
data MyStruct = { field1 :: String, field2 :: Integer, field3 :: Float} deriving (Eq, Show)
retrieveClient3 :: Connection -> Int -> IO [Only MyStruct]
retrieveClient3 conn cid = MyStruct (query conn "SELECT ticker FROM spot_daily WHERE id = ?" $ (Only cid))
但这会导致不同的错误。
作为对评论的回应,以下是 spot_daily 的架构:
Table "public.spot_daily"
Column | Type | Collation | Nullable | Default
-----------+-----------------------+-----------+----------+----------------------------------------
id | integer | | not null | nextval('spot_daily_id_seq'::regclass)
ticker | character varying(20) | | not null |
epoch | bigint | | not null |
p_open | double precision | | |
p_close | double precision | | |
p_high | double precision | | |
p_low | double precision | | |
synthetic | boolean | | |
Indexes:
"spot_daily_pkey" PRIMARY KEY, btree (id)
I am new to PostgreSQL.Simple so please forgive if question is dumb.
I am going through this tutorial: Postgresql Data Access with Haskell
I got the first demo program to run.
Now I am taking this function:
retrieveClient :: Connection -> Int -> IO [Only String]
retrieveClient conn cid = query conn "SELECT ticker FROM spot_daily WHERE id = ?" $ (Only cid)
and wish to modify it to return IO [(String, Integer, Float)]
.
So I wrote:
retrieveClient2 :: Connection -> Float -> IO [(String, Integer, Float)]
retrieveClient2 conn cid = query conn "SELECT (ticker, timestamp, some_val) FROM spot_daily WHERE p_open > ?" $ (Only cid)
main :: IO ()
main = do
conn <- connect localPG
mapM_ print =<< (retrieveClient2 conn 50.0)
and I get this:
MyApp-exe.EXE: Incompatible {errSQLType = "record", errSQLTableOid = Nothing, errSQLField = "row", errHaskellType = "Text", errMessage = "types incompatible"}
It's common in the Haskell world to say, "Search for the type signature you want on Hackage!" but it's not clear to me from the error message what type signature would make GHC happy.
Is there a conversion function for this sort of thing? I tried doing this:
data MyStruct = { field1 :: String, field2 :: Integer, field3 :: Float} deriving (Eq, Show)
retrieveClient3 :: Connection -> Int -> IO [Only MyStruct]
retrieveClient3 conn cid = MyStruct (query conn "SELECT ticker FROM spot_daily WHERE id = ?" $ (Only cid))
but that results in a different error.
In response to a comment, here is schema for spot_daily:
Table "public.spot_daily"
Column | Type | Collation | Nullable | Default
-----------+-----------------------+-----------+----------+----------------------------------------
id | integer | | not null | nextval('spot_daily_id_seq'::regclass)
ticker | character varying(20) | | not null |
epoch | bigint | | not null |
p_open | double precision | | |
p_close | double precision | | |
p_high | double precision | | |
p_low | double precision | | |
synthetic | boolean | | |
Indexes:
"spot_daily_pkey" PRIMARY KEY, btree (id)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
PostgreSQL 类型区分“行”和“记录”。正如所写的(带括号),您的 SQL 查询返回一条记录,该记录不是由元组的
FromRow
实例处理的。更改查询(通过删除括号),使其返回一行,
postgresql-simple
应该能够处理:PostgreSQL types make a distinction between a "row" and a "record". As written (with parentheses), your SQL query is returning a record, which isn't handled by the
FromRow
instance for tuples.Changing the query (by removing the parentheses), makes it return a row, which
postgresql-simple
should be able to handle: