haskell postgresql-simple 不兼容类型 _int8 和 Int64(和 Integer)

haskell postgresql-simple incompatible type _int8 and Int64 (and Integer)

下面的错误函数是名为 subdivide 的程序的一部分,该程序在服务器端处理 Postgis 地理空间交叉点,并在客户端处理 returned 的 Int64 数组。

在 Stack 下构建并 运行,解析为 Nightly 2016-08-02 并明确指定架构 x86_64。

我在执行定义为 "intersectionsSql" 的 Postgres 查询时遇到以下 运行 时间错误(请参阅此处的评论运行时错误):

"Created table:  server : [Only {fromOnly = \"PostgreSQL 9.6beta2 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit\"}] quadrant: BOX3D(-180.0 90.0, -90.0 45.0)"
subdivide: Incompatible {errSQLType = "_int8", errSQLTableOid = Nothing, errSQLField = "object_ids", errHaskellType = "Int64", errMessage = "types incompatible"}

我已经尝试了 Integer、Int64 和 Int,结果都一样,这是违反直觉的,因为根据 PostgreSQL-simple,那些 Haskell 类型应该都与 _int8 兼容实例文档:

https://hackage.haskell.org/package/postgresql-simple-0.5.0.0/candidate/docs/Database-PostgreSQL-Simple-FromField.html

SQL 查询应该 return 一行 postgres bigint[],我已经通过 PGAdmin 确认了这一点。

有什么想法吗?

关于我如何编写代码的任何评论 - 自从我上次使用 GHC 以来已有十多年了,时代已经改变。

感谢您的考虑。

迈克·托马斯

accumulateIntersections :: Identifier -> Identifier -> ConnectInfo -> ((Double,Double),(Double,Double)) -> IO ()
accumulateIntersections sourceTable accumulationTable connectionInfo q =
let
    theBox = makeBox3D (fst (fst q)) (snd (fst q)) (fst (snd q)) (snd (snd q))
    theValue = (Only theBox)
    dropTable = [sql| DROP TABLE IF EXISTS ? CASCADE |]
    createTable = [sql| CREATE TABLE ? ( quadrant_id BIGSERIAL, area_metres_squared FLOAT8, shape GEOMETRY, object_ids BIGINT[] ) |]
    aggregateSql = [sql| DROP AGGREGATE IF EXISTS _array_agg (anyarray);
                         CREATE AGGREGATE _array_agg(anyarray) (SFUNC = array_cat, STYPE = anyarray);
                        |]
    intersectionsSql = [sql| SELECT _array_agg (object_ids) object_ids
                             FROM ?
                             WHERE ST_Intersects(ST_SetSRID ( ?::box3d, 4326 ), shape)
                          |]
    insertIntersections = [sql| INSERT INTO ? (shape, object_ids)
                                VALUES ( ST_SetSRID ( ?::box3d, 4326 )
                                        , ? ) |]
in
do
  connection <- connect connectionInfo
  execute_ connection aggregateSql
  postgresVersion <- (query_ connection "SELECT version()" :: IO [Only String])
  i0 <- execute connection dropTable (Only accumulationTable)
  i1 <- execute connection createTable (Only accumulationTable)
  print ("Created table:  server : " ++ (show postgresVersion) ++ " quadrant: " ++ theBox)
  is :: [Only Int64] <- query connection intersectionsSql (sourceTable, theBox) -- RUNTIME ERROR HERE
  print ("Intersections done.")
  ids::[Int64] <- forM is (\(Only id) -> return id)
  print ("Ids done.")
  close connection
  return ()

请参阅 LP Smith 转达的上述评论,当这里没有答案时我联系了他。它解决了我的问题。

关键是要认识到 _int8 代表一个 8 字节整数数组,而不是像我那样认为它是单个 8 字节整数的内部表示。 Leon 建议的更改是在上面标记为运行时错误点的行中用“[Only (Vector Int64)]”替换“[Only Int64]”。

谢谢里昂。