Row count and similar in Esqueleto

203 Views Asked by At

Ok, I'll be more concrete

{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}

import Database.Persist.TH
import Database.Persist.Sqlite
import Database.Esqueleto
import Control.Monad.IO.Class

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Topic
   title String
|]

main :: IO ()
main = do
  runSqlite "test.sqlite" $ do
       runMigration migrateAll
       [Value c1] <- select $
                     from $ \t ->
                     do
                           return countRows
       liftIO $ putStrLn $ show (c1 :: Int)

This code causes an error

est2.hs:26:22: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘from’
  prevents the constraint ‘(From
                              SqlQuery SqlExpr SqlBackend a0)’ from being solved.
  Probable fix: use a type annotation to specify what ‘a0’ should be.

That is because the compiler does not know, which table it must use to calculate the count of rows. This thing may be done with a workaround like

   [Value c1] <- select $
                 from $ \t ->
                     do
                       orderBy [asc (t ^. TopicTitle)]
                       return countRows
   liftIO $ putStrLn $ show (c1 :: Int)

However, this is awkful, dull and artifical. Is there another, simplier way to fix this code?

The answer is:

We ought to state the table, in which the rows will be counted. The easiest way for this is to use ScopedTypeVariables language extension, and describe locally the types of arguments:

[Value c2] <- select $ from $ \(_ :: SqlExpr (Entity Topic)) -> do return countRows

0

There are 0 best solutions below