haskell-beam / haskell-beam/beam
Inference problems with insertions
- Dominant language
- Haskell
- Stars
- 635
- Forks
- 193
- PR merge metrics
- No merged PRs in 30d
Description
Hi,
I'm in the process of trying out this library. After a gruelling day and a half spent wrangling my ten tables into beam-migrate and trying to figure out beam-migrate-cli (and staying with autoMigrate in the end), I'm finally in trying to write my first query. I'm translating the core of another application that uses Persistent - what drove me to try this out is the support for mixins, which I'm trying to use to the fullest.
Anyway, the query I'm trying to build is just a simple text fixture for inserting users:
```
addUsers :: Pg ()
addUsers = do
now <- zonedTimeToLocalTime <$> liftIO getZonedTime
users <- forM ["admin", "user"] $ \u -> do
hash <- liftIO $ T.pack . BS.unpack <$> makePassword (BS.pack $ T.unpack u) 17
return $ User default_ (val_ u) (just_ $ val_ hash) (val_ True) (emptyBlamable Nothing)
runInsert . insert (user starletDb) $ insertExpressions users
```
The problem I have is with the `s` (scope?) that `insertExpressions` is forall'd over and the GHC tells me that it `Couldn't match type ‘s’ with ‘s'’ because type variable ‘s'’ would escape its scope`.
Trying to explicitly annotate `users :: [forall s. UserT (QExpr PgExpressionSyntax s)] <- ...` causes the compiler to give up with the error `llegal polymorphic type: forall s. QExpr syntax s. GHC doesn't yet support impredicative polymorphism`.
The only (ugly) solution I can think of is to use a newtype to hide the `s` parameter, though I'm not sure that'd work the way I expect it to.
I did manage to make the query work by moving the `User` construction inside `insertExpressions`:
```
addUsers :: Pg ()
addUsers = do
now <- zonedTimeToLocalTime <$> liftIO getZonedTime
users <- forM ["admin", "user"] $ \u -> do
hash <- liftIO $ T.pack . BS.unpack <$> makePassword (BS.pack $ T.unpack u) 17
return (u, hash)
runInsert . insert (user starletDb) $ insertExpressions $ flip fmap users $ \(u, p) ->
User default_ (val_ u) (just_ $ val_ p) (val_ "") (val_ True) (emptyBlamable Nothing)
```
That solves this particular problem, but I'd like to know how to do it with the first construction (if it's possible to convince the compiler...).
Also, I've stumbled upon another inference-related problem - replacing `runInsert $ insert (user starletDb) $ insertExpressions $ flip fmap users $ ...` by the nicer point-free version `runInsert . insert (user starletDb) . insertExpressions . flip fmap users $ ...` causes the compiler to want to infer `[UserT (QExpr syntax s)]` with a unified `s` - whereas the immediately applied version keeps the `forall s.`.
I'm sure there is an easy solution to both of these, but while I've played with TypeFamilies et al. quite a bit, I haven't really used this type of nested `forall`s yet, so I'm reduced to having a one-sided conversation with GHC :)
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.