Hello, (belated) happy new year everyone!
We’ve just released Rel8 1.4.1.0. Rel8 is a Haskell library for interacting with PostgreSQL databases, built on top of the fantastic Opaleye library.
There are a lot of goodies in this release, including support for window functions, GHC 9.4 support, bug fixes, and more. For a complete list of changes, see the release notes.
Happy querying!
10 Likes
Window functions are very useful, glad that they’re now supported!
For Nix users who want a quick Rel8 playground, this repo’s shell.nix
sets up Postgres and loads the “Pagila” example database. File Rel8Main.hs
contains Rel8
TableSchema
s for the main tables in the database, from which to construct Query
s using each
.
3 Likes
@ocharles While trying to wrap my head around Rel8
, I wrote the following paragraphs to put my ideas in order. Would you say that they are a correct description of how the Query
monad works?
Query
, while being a monad, is a carefully controlled one. Everything bound to the left of <-
won’t be a “plain” value, but one wrapped in an Expr
context. Primitive types are wrapped like Expr Int
. Record types will have each of its components wrapped in Expr
, and it will look like Person Expr
. We can also have tuples like (Expr Int, Person Expr)
.
Inside the Query
monad, you won’t pattern match on sum types directly, in the conventional way, using case
. Instead, you’ll use functions like maybeTable or deconstructADT that “shift” the pattern-match into the Expr
world.
Also, inside Query
type signatures, you shouldn’t use constructors like Maybe
to signify the absence of a value, or Either
to signify alternatives. Instead of them, you need to use MaybeTable
and EitherTable
. A common source of MaybeTable
s is the optional
function.
We can think of select
as a function that removes Expr
wrappers, giving us direct access to values, and also converts MaybeTable
and EitherTable
into Maybe
and Either
, respectively.
So that’s definitely not true. Consider a <- pure (1 :: Int)
, for example. a :: Int
isn’t wrapped in an “Expr
context”. I think it is true, however, that the value of anything bound to the left of <-
that’s not in an “Expr
context”, will be statically known with respect to the query, i.e. its value is known before the query runs.
1 Like
You’re right, of course. And you can pattern-match normally on them as well. I didn’t think of that because I only use Query
's pure
for recombining Expr
-wrapped values previously obtained from the SQL side.
1 Like
It’s hard to give a definitive answer, but it looks like your intuition is right. It’s difficult to say things like “you don’t use case
when in the Query
monad”, because there are many times when you can/will do that (e.g., when combining multiple Expr
s into a Table
and later unpacking them with pattern matching). Other than that I think you’ve got the right idea!