[Haskell-cafe] Selda: confused about type signtures

Marc Busqué marc at lamarciana.com
Fri Apr 20 18:33:10 UTC 2018


Hi!

I'm using [selda](https://hackage.haskell.org/package/selda) package in
order to deal with database backends.

Selda uses `TypeOperators` language extension, and it introduces  `:*:`
type operator constructor which take concrete types like `RowID` or
`Text` . It also has a `Table` type constructor which takes anything
built with `:*:`). On the other hand, `SeldaM` is selda custom monad
transformer with `IO` at the bottom.

I have following helper function which just wraps a call to the SQLite
backend. `dBPath` is just the database file path:

```
withDB :: SeldaM a -> IO a
withDB act = do
   path <- dBPath
   withSQLite path act
```

I want to wrap selda API in custom functions to be more resilient to
changes. Right now I'm trying to abstract selecting all rows for a given
table (maybe it seems brittle, but it is just a toy project in order to
learn Haskell):

```
list table = withDB $ query (select table) 
```

Not adding a type signature to `list` produces following compilation
error:

```
• Non type-variable argument
     in the constraint: selda-0.1.12.1:Database.Selda.Column.Columns
                          (selda-0.1.12.1:Database.Selda.Column.Cols s a)
   (Use FlexibleContexts to permit this)
• When checking the inferred type
     list :: forall s a.
             (selda-0.1.12.1:Database.Selda.Column.Columns
                (selda-0.1.12.1:Database.Selda.Column.Cols s a),
              selda-0.1.12.1:Database.Selda.Compile.Result
                (selda-0.1.12.1:Database.Selda.Column.Cols s a)) =>
             Table a
             -> IO
                  [selda-0.1.12.1:Database.Selda.Compile.Res
                     (selda-0.1.12.1:Database.Selda.Column.Cols s a)]
```

If I try to add what I think would be the correct signature:

```
list :: Table a -> IO [a]
```

The error changes to:

```
• Couldn't match type ‘a’
                  with ‘selda-0.1.12.1:Database.Selda.Compile.Res
                          (selda-0.1.12.1:Database.Selda.Column.Cols s0 a)’
   ‘a’ is a rigid type variable bound by
     the type signature for:
       list :: forall a. Table a -> IO [a]
     at src/Hedger/Category.hs:35:1-25
   Expected type: SeldaM [a]
     Actual type: selda-0.1.12.1:Database.Selda.Backend.Internal.SeldaT
                    IO
                    [selda-0.1.12.1:Database.Selda.Compile.Res
                       (selda-0.1.12.1:Database.Selda.Column.Cols s0 a)]
• In the second argument of ‘($)’, namely ‘query (select table)’
   In the expression: withDB $ query (select table)
   In an equation for ‘list’:
       list table = withDB $ query (select table)
• Relevant bindings include
     table :: Table a (bound at src/Hedger/Category.hs:36:6)
     list :: Table a -> IO [a] (bound at src/Hedger/Category.hs:36:1)
    |
36 | list table = withDB $ query (select table)
```

However, if I constraint the type signature to act just for a given
table, it compiles without errors:

```
type CategoriesSchema = RowID:*:Text
list :: Table CategoriesSchema -> IO [CategoriesSchema]
```

Why is that it works with concrete types but not with a type variable
that takes the same concrete type in its both placeholders?

Thanks in advance,

Marc Busqué
http://waiting-for-dev.github.io/about/


More information about the Haskell-Cafe mailing list