bitemyapp / bitemyapp/esqueleto
a monad for sqlexpr
- Dominant language
- Haskell
- Stars
- 399
- Forks
- 107
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 1
Description
thinking that it'd be nice to have a monad for SqlExpr to make it a bit easier and clearer how to write code with it
```haskell
newtype SqlExprM a = SqlExprM (ReaderT NeedsParens (ReaderT IdentInfo (Writer (TLB.Builder, [PersistValue])) a)
unSqlExprM :: SqlExprM () -> NeedsParens -> IdentInfo -> (TLB.Builder, [PersistValue])
unSqlExprM (SqlExprM expr) np ident =
execWrtier $ runReaderT (runReaderT expr np) ident
instance (a ~ ()) => IsString (SqlExprM a) where
fromString str = tell (fromString str, [])
param :: (PersistField a) => a -> SqlExprM ()
param a = tell ("?", [toPersistValue a])
```
This makes it much easier to write raw SQL expressions. Taking the example from [the Finally Tagless blog post](https://www.foxhound.systems/blog/final-tagless/), we could write:
```haskell
bool :: Bool -> SqlExpr Bool
bool b = param b
int :: Int -> SqlExpr Int
int i = param i
paren :: SqlExpr a -> SqlExpr a
paren = local (\_ -> True)
leq :: SqlExpr Int -> SqlExpr Int -> SqlExpr Bool
leq e1 e2 = do
paren e1
" <= "
paren e2
and_ :: SqlExpr Bool -> SqlExpr Bool -> SqlExpr Bool
and_ e1 e2 = do
paren e1
" AND "
paren e2
binop :: Builder -> SqlExpr a -> SqlExpr b -> SqlExpr c
binop op e1 e2 = do
paren e1
" "
tell (op, [])
" "
paren e2
or_ :: SqlExpr Bool -> SqlExpr Bool -> SqlExpr Bool
or_ = binop "OR"
op :: Builder -> SqlExpr a -> SqlExpr b
op x a =
tell (x, [])
" "
a
not_ :: SqlExpr Bool -> SqlExpr Bool
not_ = op "NOT"
where_ :: SqlExpr Bool -> (Builder, [PersistValue])
where_ e =
unSqlExprM e False
```
Needs some work to get the types to check but overall may be a nice UX improvement
Contributor guide
No contributing guide indexed for this repository
Research direction
No files or tests are named. Start by reviewing the existing SqlExpr implementation and the proposed SqlExprM design in this issue, then determine the required type corrections and API shape; done means the monad provides the intended raw-SQL expression UX and the examples type-check.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- haskell
- Domain
- databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100