0

I have a query I'm running in Hasql using Hasql.TH, and I'm encountering an error I've never seen before (see below). I'm seen this SO question/answer which references the version of vector, but (a) I'm using stack so these things should be resolved (right?); (b) the version of vector isn't highlighted in the error, and I'm not pinning the version in my package.yaml, so I don't think that's the problem (but I'm not sure how to verify this).

So, is is plausible that this is to do with versions of the library (I've never seen this sort of thing happen) or is there another issue I'm missing?

The query is as follows:

writeEvents :: [EventRow 'NewRecord] -> Session [EventID]
writeEvents =
  flip statement $
    dimap
      (unzip7 . map eventToRow)
      (toList . fmap (mkEventID . toInteger))
      [vectorStatement|
    insert into events (
      title,
      description,
      url,
      venue_id,
      start_date,
      end_date,
      origination
    ) (
      select 
        cols.title,
        cols.description,
        cols.url,
        venues.id,
        cols.start_date,
        cols.end_date,
        cols.origination
      from unnest (
        $1 :: text[],
        $2 :: text?[],
        $3 :: text?[],
        $4 :: text[],
        $5 :: timestamptz[],
        $6 :: timestamptz[],
        $7 :: text[]
      ) as cols (title, description, url, venue_name, start_date, end_date, origination)
      left join venues on (cols.venue_name = venues.name)
    )
    returning (id :: int4)
  |]
1. No instance for (Data.Vector.Generic.Base.Vector [] (Maybe Text))
       arising from a use of ‘Data.Vector.Generic.foldl'’
   • In the first argument of ‘hasql-1.6.3:Hasql.Private.Encoders.dimension’, namely
       ‘Data.Vector.Generic.foldl'’
     In the first argument of ‘hasql-1.6.3:Hasql.Private.Encoders.array’, namely
       ‘((hasql-1.6.3:Hasql.Private.Encoders.dimension
            Data.Vector.Generic.foldl')
           (hasql-1.6.3:Hasql.Private.Encoders.element
              (hasql-1.6.3:Hasql.Private.Encoders.nullable
                 hasql-1.6.3:Hasql.Private.Encoders.text)))’
     In the first argument of ‘hasql-1.6.3:Hasql.Private.Encoders.nonNullable’, namely
       ‘(hasql-1.6.3:Hasql.Private.Encoders.array
           ((hasql-1.6.3:Hasql.Private.Encoders.dimension
               Data.Vector.Generic.foldl')
              (hasql-1.6.3:Hasql.Private.Encoders.element
                 (hasql-1.6.3:Hasql.Private.Encoders.nullable
                    hasql-1.6.3:Hasql.Private.Encoders.text))))’```
GTF
  • 8,031
  • 5
  • 36
  • 59
  • From the error message, it seems like foldl is called on an empty array. Is this coming from the SQL unnest function? – Dorin Botan Jan 16 '23 at 14:34
  • The Hasql documentation does suggest using `unnest` as a way of inserting multiple rows (https://hackage.haskell.org/package/hasql-1.6.3/docs/Hasql-Statement.html#g:2), although I have assumed the TH support works. I'm not sure why it would relate to `unnest` though, since the variables $1 etc. are the ones with type annotations. – GTF Jan 16 '23 at 15:00
  • Ah I've worked it out. – GTF Jan 16 '23 at 18:29

1 Answers1

0

As per the errors, this is because there is no Vector instance for [] (i.e. the list functor). I needed to map my tuple of lists to a tuple of vectors. Somewhat annoyingly, in my example I'm having to use a 7-tuple, for which there is no readily available unzip7 in vector, therefore I had to write vecunzip7:

vecunzip7 :: [(a, b, c, d, e, f, g)] -> (Vector a, Vector b, Vector c, Vector d, Vector e, Vector f, Vector g)
vecunzip7 xs =
  ( fromList . map (\(a, _, _, _, _, _, _) -> a) $ xs,
    fromList . map (\(_, b, _, _, _, _, _) -> b) $ xs,
    fromList . map (\(_, _, c, _, _, _, _) -> c) $ xs,
    fromList . map (\(_, _, _, d, _, _, _) -> d) $ xs,
    fromList . map (\(_, _, _, _, e, _, _) -> e) $ xs,
    fromList . map (\(_, _, _, _, _, f, _) -> f) $ xs,
    fromList . map (\(_, _, _, _, _, _, g) -> g) $ xs
  )
GTF
  • 8,031
  • 5
  • 36
  • 59