Error when trying to query with snaplet-postgres-simple

109 Views Asked by At

I'm quite new to Haskell and Snap framework. I'm trying to implement a REST API server but I have some problems querying the Postgresql database using snaplet-postgresql-simple.

queryDatabase::(B.ByteString,B.ByteString) ->[Interactions]
queryDatabase (drug1,drug2) = do
    interaction <- query "SELECT drug1name,drug2name,interactioncode FROM interactions WHERE drug1name = ? and drug2name = ?" ((B.unpack drug1)::String, (B.unpack drug2)::String):: [Interactions]
    return interaction

getDrugList :: Handler b InteractionsService ()
getDrugList = do
  drugList <- getQueryParam "list"
  let drugs = getDrugPairs $ show drugList
  let interactionPairs = map queryDatabase drugs
  modifyResponse $ setHeader "Content-type" "application/json"
  writeLBS . encode $ (interactionPairs :: [[Interactions]])

The idea is that when the following request is made curl -XGET localhost:8000/api/interactions/drugs?list=drug1,drug2,drug3 the getDrugList function is called. In drugs I save the pairs of drugs as a list of tuples [(drug1,drug2),(drug1,drug3),(drug2,drug3)] and after that I map the function queryDatabase on the list. The problem is that when I try to compile, I get the following error:

• Couldn't match type '[r0]' with 'Interactions'
      Expected type: [Interactions]
        Actual type: [[r0]]
    • In a stmt of a 'do' block:
        interaction <- query
                         "SELECT drug1name,drug2name,interactioncode FROM interactions WHERE drug1name = ? and drug2name = ?"
                         ((B.unpack drug1) :: String, (B.unpack drug2) :: String) ::
                         [Interactions]
      In the expression:
        do interaction <- query
                            "SELECT drug1name,drug2name,interactioncode FROM interactions WHERE drug1name = ? and drug2name = ?"
                            ((B.unpack drug1) :: String, (B.unpack drug2) :: String) ::
                            [Interactions]
           return interaction
      In an equation for 'queryDatabase':
          queryDatabase (drug1, drug2)
            = do interaction <- query
                                  "SELECT drug1name,drug2name,interactioncode FROM interactions WHERE drug1name = ? and drug2name = ?"
                                  ((B.unpack drug1) :: String, (B.unpack drug2) :: String) ::
                                  [Interactions]
                 return interaction
   |
37 |     interaction <- query "SELECT drug1name,drug2name,interactioncode FROM interactions WHERE drug1name = ? and drug2name = ?" ((B.unpack drug1)::String, (B.unpack drug2)::String):: [Interactions]
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The Interactions data type is defined as:

data Interactions = Interactions
  {
    drug1name :: T.Text
  , drug2name :: T.Text
  , druginteraction :: Int
  }

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

instance ToJSON Interactions where
  toJSON (Interactions drug1name drug2name interaction) = object [ "drug1name" .= drug1name
                                                                 , "drug2name" .= drug2name
                                                                 , "interaction" .= interaction]

Any help is appreciated. I don't have any ideas on how to make it compile and work.


UPDATE

I found a workaround, probably not the best one.

makeQuery::B.ByteString->B.ByteString->Query
makeQuery drug1 drug2 = DS.fromString ("SELECT drug1,drug2,interaction FROM interactions WHERE drug1 = '"++(B.unpack drug1)++"' and drug2 = '"++(B.unpack drug2)++"'")


getDrugList :: Handler b InteractionsService ()
getDrugList = do
  drugList <- getQueryParam "list"
  let drugs = getDrugPairs $ show drugList
  modifyResponse $ setHeader "Content-type" "application/json"
  forM_ drugs $ \(drug1,drug2) -> do
   let theQuery = makeQuery drug1 drug2
   pair<-query_ theQuery
   writeLBS . encode $ (pair::[Interactions])

0

There are 0 best solutions below