
The more precise answer to your question is that an explicit type signature
is taken as exact. If the type needed is some (Ctx a => a), as here, but
your type signature just says a, you will get a type error exactly as you
did.
"a" there does not mean "figure out a type for me". It means *any type at
all*. Including Void, (), Int, etc., which one would not expect to work
there.
On Fri, Apr 20, 2018 at 2:33 PM, Marc Busqué
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/ _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net