json - postgres-simple - 没有因使用 ‘query’ 而产生的 (ToRow Int) 实例

标签 json postgresql haskell haskell-spock postgresql-simple

我是 haskell 的新手,老实说用起来很困难。但它扩展了我的思维,所以我们开始吧。 我正在尝试运行一个非常简单的网络服务器来查询 Postgres 数据库,并应将结果作为 JSON 返回。

查询非常简单: "从 MYTABLE 中选择 id,数据,其中 id = 1"

但是 haskell 的类型系统现在正在折磨我,我的行为的最终类型不匹配。 我正在使用 SpockPostgreSQL-Simple作为组合。

大多数教程要么对我想做的事情来说太简单,要么太难。我介于两者之间,错过了很多 Haskell 的理解,很多我以前的问题我已经通过简单的复制和粘贴解决了,并且得到了一个简单的版本。

但是,一旦我尝试传递一个路由变量,我就失败了。 这是我的工作版本。我的数据库表在这里称为“信封”,重要的调用是它说 get "json" 的地方:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleInstances #-}

module Main where

import Web.Spock
import Web.Spock.Config
import Database.PostgreSQL.Simple
import Data.Pool
import Data.Aeson (ToJSON(toJSON), object, (.=),Value)
import  Database.PostgreSQL.Simple.FromRow

type AppAction a = SpockActionCtx () Connection AppSession AppState a

data AppState = EmptyState
data AppSession = EmptySession

data Envelope = Envelope { envId :: Int, envData :: Value } deriving Show

instance FromRow Envelope where
  fromRow = Envelope <$> field <*> field

instance ToJSON Envelope where
   toJSON (Envelope envA envB) = object [ "id" .= envA, "data" .= envB ]

main :: IO ()
main =
  do pool<-createPool (connect (ConnectInfo "localhost" 5432 "" "" "envelopes") ) close 1 10 10
     spockCfg <- defaultSpockCfg EmptySession (PCPool pool) EmptyState
     runSpock 8080 (spock spockCfg app)

app :: SpockM Connection AppSession AppState ()
app = do 
    get root $
      text "Hello World!"
    get "json" $ do
      xs<-runQuery $ \conn -> 
        query_ conn  "select id,data from envelope where id = 1"
      json (xs::[Envelope])

然后我尝试使用 lambda 函数传递信封 ID,为此我还需要将 PostgreSQL-Simple query_ 更改为 query:

    get ( "json" <//> var  ) $ \eid -> do
      xs<-runQuery $ \conn -> 
        query conn  "select id,data from envelope where id = ?" (eid :: Int)
      json (xs::[Envelope])

我得到的错误是:

 No instance for (ToRow Int) arising from a use of ‘query’
   In the expression:
      query conn "select id,data from envelope where id = ?" (eid :: Int)
    In the second argument of ‘($)’, namely
      ‘\ conn
         -> query
              conn "select id,data from envelope where id = ?" (eid :: Int)’
    In a stmt of a 'do' block:
      xs <- runQuery
            $ \ conn
                -> query
                     conn "select id,data from envelope where id = ?" (eid :: Int)

即使没有 lambda 函数,我也无法仅从查询中返回第一项。

可以在 bitbucket 上找到完整的源代码

我希望有人有时间在这里帮助我。 感谢您阅读。

最佳答案

错误基本上是说您不能将 Int 作为第三个参数传递给 queryquery 期望具有类型类 ToRow 实例的内容而 Int 不是一个。考虑到您只想将一个值传递给 query,在您的情况下您可能想要做的是使用 Only .所以那一行变成:

query conn  "select id,data from envelope where id = ?" (Only (eid :: Int))

关于json - postgres-simple - 没有因使用 ‘query’ 而产生的 (ToRow Int) 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42423736/

相关文章:

haskell - 有理数的平方根

java - 使用 JsonTypeInfo.As.EXTERNAL_PROPERTY 而不指定 @JsonSubTypes

json - solr 使用 json 更新导致 'error parsing json field. unexpected object_start'

javascript - 解构嵌套对象 es6

postgresql - 在 PL/pgSQL 中声明记录的元组结构

haskell - 如何为状态类型不透明的有状态组件创建接口(interface)?

json - Angular2 使用 typescript 映射和迭代 JSON 对象

django - 从查询集中的 jsonfield 中选择值

python - 一般新闻的新闻提要 API

string - Haskell 操作文件内容