bitemyapp / esqueleto

New home of Esqueleto, please file issues so we can get things caught up!
BSD 3-Clause "New" or "Revised" License
372 stars 107 forks source link

missing :& #382

Closed KeesBleijenberg closed 9 months ago

KeesBleijenberg commented 9 months ago

In a Yesod project I upgraded to version 3.5.11.0

{-# LANGUAGE TypeApplications #-} import Database.Esqueleto.Experimental

personen <-  runDB $ select $ do 
                                                      (persoon :& adres) <- 
                                                                from table@Persoon `innerJoin` table@Adres 
                                                                `on` (\(p :& a) -> p ^. PersoonAdresId ==. a ^. AdresId
                                                      return persoon 

The persistmodel:

Adres  json 
    street Text Maybe 
    ...
Persoon json 
     firstName Text Maybe 
     adresId AdresId
    ....

I have many problems with this code, but the first problem is that the compiler can't find :& Where is it? Any other helpfull ideas?

Kees

parsonsmatt commented 9 months ago

If you write:

import Database.Esqueleto.Experimental ((:&)(..))

does it give an error?

KeesBleijenberg commented 9 months ago

No other references then this line: import Database.Esqueleto.Experimental ((:&)(..))

Results in a lot of errors. The compiler can't find select, from, table, innerjoin, on, and ^.

I'am using ghc version 9.4.8 In package.yaml I have the line: esqueleto >= 3.5.11.0

parsonsmatt commented 9 months ago

Ok, interesting. That means esqueleto does have the :& constructor in scope. Can you post the full error output you're seeing?

KeesBleijenberg commented 9 months ago

Ok, interesting. That means esqueleto does have the :& constructor in scope. Can you post the full error output you're seeing?

I tried deleting the .stack directory and I did a stack clean --full. In the import is the line import Database.Esqueleto.Experimental ((:&) (..))

Building library for adressen-0.0.0.. [26 of 40] Compiling Handler.Personen

/home/kees/adressen/src/Handler/Personen.hs:31:25: error: Variable not in scope: select :: ((t4 :& AdresId) -> b2) -> ReaderT SqlBackend (HandlerFor App) (t5 a0) Suggested fixes: • Perhaps use ‘selected’ (imported from Handler.AdressenHuFu) • Perhaps you want to add ‘select’ to the import list in the import of ‘Database.Esqueleto.Experimental’ (src/Handler/Personen.hs:19:1-50). | 31 | personen <- runDB $ select $ do | ^^^^^^

/home/kees/adressen/src/Handler/Personen.hs:33:64: error: Variable not in scope: from :: t1 -> t2 Suggested fix: Perhaps you want to add ‘from’ to the import list in the import of ‘Database.Esqueleto.Experimental’ (src/Handler/Personen.hs:19:1-50). | 33 | from (table @Persoon) innerJoin (table @Adres) | ^^^^

/home/kees/adressen/src/Handler/Personen.hs:33:71: error: Variable not in scope: table Suggested fix: Perhaps you want to add ‘table’ to the import list in the import of ‘Database.Esqueleto.Experimental’ (src/Handler/Personen.hs:19:1-50). | 33 | from (table @Persoon) innerJoin (table @Adres) | ^^^^^

/home/kees/adressen/src/Handler/Personen.hs:33:87: error: Variable not in scope: innerJoin :: t2 -> t3 -> b1 -> b1 -> c0 Suggested fix: Perhaps you want to add ‘innerJoin’ to the import list in the import of ‘Database.Esqueleto.Experimental’ (src/Handler/Personen.hs:19:1-50). | 33 | from (table @Persoon) innerJoin (table @Adres) | ^^^^^^^^^^^

/home/kees/adressen/src/Handler/Personen.hs:33:100: error: Variable not in scope: table Suggested fix: Perhaps you want to add ‘table’ to the import list in the import of ‘Database.Esqueleto.Experimental’ (src/Handler/Personen.hs:19:1-50). | 33 | from (table @Persoon) innerJoin (table @Adres) | ^^^^^

/home/kees/adressen/src/Handler/Personen.hs:34:90: error: Variable not in scope: (^.) :: t4 -> Filter Persoon -> t0 Suggested fixes: • Perhaps use one of these: ‘.’ (imported from Import), ‘^’ (imported from Import), ‘<.’ (imported from Import) • Perhaps you want to add ‘^.’ to the import list in the import of ‘Database.Esqueleto.Experimental’ (src/Handler/Personen.hs:19:1-50). | 34 | on (p :& a) -> p ^. PersoonAdresId ==. a ^. AdresId | ^^

/home/kees/adressen/src/Handler/Personen.hs:34:115: error: Variable not in scope: (^.) :: t0 -> EntityField Adres AdresId -> b1 Suggested fixes: • Perhaps use one of these: ‘.’ (imported from Import), ‘^’ (imported from Import), ‘<.’ (imported from Import) • Perhaps you want to add ‘^.’ to the import list in the import of ‘Database.Esqueleto.Experimental’ (src/Handler/Personen.hs:19:1-50). | 34 | on (p :& a) -> p ^. PersoonAdresId ==. a ^. AdresId | ^^ .....

Error: [S-7282] Stack failed to execute the build plan.

   While executing the build plan, Stack encountered the error:

   [S-7011]
   While building package adressen-0.0.0 (scroll up to its section to see the error) using:
   /home/kees/.stack/setup-exe-cache/x86_64-linux-tinfo6/Cabal-simple_6HauvNHV_3.8.1.0_ghc-9.4.8 --verbose=1 --builddir=.stack-work/dist/x86_64-linux-tinfo6/Cabal-3.8.1.0 build lib:adressen exe:adressen --ghc-options ""
   Process exited with code: ExitFailure 1

It looks like Esqueleto expermimental doesn't export anything

parsonsmatt commented 9 months ago

Try it with the open import. The "only import (:&)(..)" request was to see if GHC gave an error about that import not being available.

KeesBleijenberg commented 9 months ago

Try it with the open import. The "only import (:&)(..)" request was to see if GHC gave an error about that import not being available.

What do you mean with 'open import' I tried: import Database.Esqueleto.Experimental and got

Building all executables for adressen once. After a successful build of all of them, only specified executables will be rebuilt. adressen> build (lib + exe) Preprocessing library for adressen-0.0.0.. Building library for adressen-0.0.0.. [26 of 40] Compiling Handler.Personen

/home/kees/adressen/src/Handler/Personen.hs:41:70: error: Ambiguous occurrence ‘on’ It could refer to either ‘Import.on’, imported from ‘Import’ at src/Handler/Personen.hs:18:1-13 (and originally defined in ‘Data.Function’) or ‘Database.Esqueleto.Experimental.on’, imported from ‘Database.Esqueleto.Experimental’ at src/Handler/Personen.hs:19:1-38 (and originally defined in ‘Database.Esqueleto.Experimental.From.Join’) | 41 | on (p :& a) -> p ^. PersoonAdresId ==. a ^. AdresId | ^^^^

/home/kees/adressen/src/Handler/Personen.hs:41:109: error: Ambiguous occurrence ‘==.’ It could refer to either ‘Import.==.’, imported from ‘Import’ at src/Handler/Personen.hs:18:1-13 (and originally defined in ‘Database.Persist’) or ‘Database.Esqueleto.Experimental.==.’, imported from ‘Database.Esqueleto.Experimental’ at src/Handler/Personen.hs:19:1-38 (and originally defined in ‘Database.Esqueleto.Internal.Internal’) | 41 | on (p :& a) -> p ^. PersoonAdresId ==. a ^. AdresId | ^^^

The solution seems to be to import Database.Esquelete.Experimental qualified. This is what was my first attempt.

import qualified Database.Esqueleto.Experimental as E ... personen <- runDB $ E.select $ do (persoon E.:& adres ) <- do E.from (E.table @Persoon) E.innerJoin (E.table @Adres) E.on (p E.:& a) -> p E.^. PersoonAdresId E.==. a E.^. AdresId return persoon

But then I got /home/kees/adressen/src/Handler/Personen.hs:40:64: error: • Couldn't match type ‘E.From’ with ‘E.SqlQuery’ Expected: E.SqlQuery (E.SqlExpr (Entity Persoon) E.:& E.SqlExpr (Entity Adres)) Actual: E.From (E.SqlExpr (Entity Persoon) E.:& E.SqlExpr (Entity Adres)) • In a stmt of a 'do' block: E.from (E.table @Persoon) E.innerJoin (E.table @Adres) E.on \ (p E.:& a) -> p E.^. PersoonAdresId E.==. a E.^. AdresId In a stmt of a 'do' block: (persoon E.:& adres) <- do E.from (E.table @Persoon) E.innerJoin (E.table @Adres) E.on \ (p E.:& a) -> p E.^. PersoonAdresId E.==. a E.^. AdresId In the second argument of ‘($)’, namely ‘do (persoon E.:& adres) <- do E.from (E.table @Persoon) E.innerJoin (E.table @Adres) E.on \ (p E.:& a) -> ... return persoon’ | 40 | E.from (E.table @Persoon) E.innerJoin (E.table @Adres) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... What a error message :-(

Do I have to use on, from...(?) from other libraries?

belevy commented 9 months ago

The precedence on from is too high since it is just function application. You need to throw a ($) after from.

KeesBleijenberg commented 9 months ago

The precedence on from is too high since it is just function application. You need to throw a ($) after from.

Thank you. This solves the problem. Hard to find, at least for me.

belevy commented 9 months ago

Yah not sure if there is a way to make it work without the need to use the application operator or parentheses.

I happen to be fairly good at keeping precedence rules in my head and have seen this particular precedence issue before.