Haskell:GHC不能推断出类型。刚性类型变量受到类型签名错误的限制 [英] Haskell: GHC cannot deduce type. Rigid type variable bound by the type signature error
问题描述
我看过一些类似主题的帖子,但他们并没有真正帮助我解决问题。所以我敢重复。
现在我有一个带签名的函数:
run':: Expr query => RethinkDBHandle - >查询 - > IO [JSON]
这是一个数据库查询运行函数。
我将这个函数包装在一个池中(池已经创建并且与问题无关),以简化连接。
rdb q = withResource pool(\ h - > run'(use h $ dbtest)q)
基本上,这个函数的签名与上面的run完全一样。
问题是如果我使用没有签名的函数,那么所有好,GHC很高兴搞清楚事情。一旦我指定了签名,它就会停止对某些输入进行处理,抱怨无法推断该类型。
主要有两种输入类型用作查询输入。
ReQL和表
这两种类型都是 Expr
的实例,所以它们都被GHC接受。
只要我把签名一切停止工作,GHC coplains关于不能推断类型,并给我由类型签名绑定的刚性类型变量错误。如果我使签名更具体,比如 ReQL
而不是 Expr a
,那么很明显它会停止接受表
输入,反之亦然。将输入指定为 Expr a
,其中 ReQL
和表
是上述错误的例子。所有放在一起的签名都可以正常工作。
那么我该如何解决这个问题?删除签名感觉不对。
我不知道我是否应该使问题更通用或更具体,但如果它有帮助,这是图书馆与所有类型和实例来帮助建议。
更新 $ b
根据要求,这是产生错误的完整代码清单。
main = do
pool< - createPool(connectlocalhost28015 Nothing)close 1 300 5
让rdb q = with资源池(\ h - > run'(使用h $ dbtest)q)
scotty 3000 $ basal rdb
basal :: Expr q => (q - > IO [JSON]) - > ScottyM()
basal r = get/ json$ showJson r
showJson :: Expr q => (q - > IO [JSON]) - > ActionM()
showJson r = do
j< - lift $ r $ tablemytable
text $ T.pack $ show j
这是完整的错误列表
Main。 hs:19:17:
由于使用`basal'
而没有实例(Expr q0)类型变量`q0'不明确
可能的修正:添加修复的类型签名
实例
实例Expr() - 在`Database.RethinkDB.ReQL'中定义
实例(Expr a,Expr b)= > Expr(a,b)
- 在`Database.RethinkDB.ReQL'中定义
实例(Expr a,Expr b,Expr c)=> Expr(a,b,c)
- 在`Database.RethinkDB.ReQL'中定义
...加上24个
在`($)'的第二个参数中,基本rdb'
在'do'块的标记中:scotty 3000 $ basal rdb
在表达式中:
do {pool< - createPool
(connectlocalhost 28015无)close 1 300 5;
让rdb q = withResource pool(\ h - > ...);
scotty 3000 $ basal rdb}
Main.hs:26:19:
无法从上下文推断(q〜Table)
(Expr q)
绑定
的类型签名showJson :: Expr q => (q - > IO [JSON]) - > ActionM()
在Main.hs:24:13-52
`q'是由$ b $绑定的刚性类型变量
的类型签名showJson :: Expr q => ; (q - > IO [JSON]) - > ActionM()
在Main.hs:24:13
在`table'调用的返回类型中
在`($)'的第二个参数中,即`tablemytable ''
在`($)'的第二个参数中,即`r $ table'mytable''
谢谢
读取错误信息看起来第一个问题是您为 showJson
是错误的。
由于 r
表
即 table :: String - >表
其类型不是
r :: Expr q => ; q - > IO [JSON]
而不是
r :: Table - > IO [JSON]
或(使用 RankNTypes
)
r :: forall q。 Expr q => q - > IO [JSON]
第一个更简单,更直接,第二个可能更接近您的意图---它可以被读为 fromJson
所需的输入只在其参数中使用 Expr
接口而不是 fromJson
采用任何一种恰巧使用 Expr
实例化类型作为参数的输入。例如,用你给出的类型
fromJson(undefined :: Query - > IO [JSON])
会统一起来......但显然现在是 (具体来说,它与参数 现在,很好地导致 或 因此导致您的 此时我不确定为什么指定显式类型 I'v seen a couple of posts with a similar subject but they don't really help me to solve my problem. So I dare to repeat. Now I have a functions with signature: this is a database query run function. I wrap this function in a pool (pool is already created and irrelevant to the question) to simplify connections. Essentially, this function has exact the same signature as the run above. The problem is that if I use the function without a signature then all is good and GHC is happy figuring things out. As soon as I specify the signature it stops working on certain input complaining about not being able to deduce the type. There are mainly two input types that are used as query input. Both of those types are instances of As soon as I put the signature everything stops working and GHC coplains about not being able to deduce the type and gives me "rigid type variable bound by the type signature" error. If I make signature more specific like So how do I solve this? Dropping the signature feels wrong. I don't know if I should make the question more generic or more specific but if it helps this is the library with all the types and instances to help with an advice. UPDATE As requested, this is the full code listing producing the error. And this is the full error listing Thank you Reading the error messages it seems the first problem is that the type you specify for As but instead either or (using The first is simpler and more direct while the second is probably closer to your intended meaning---it can be read as " would unify as well... but clearly that's now how (In particular, it has to do with the positivity of the parameter Now, this specificity of type transmits upward as well causing or and thus leading to your At this point I can't be sure why stating an explicit type for 这篇关于Haskell:GHC不能推断出类型。刚性类型变量受到类型签名错误的限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! r $ c
q $>的积极性有关c $ c>。由于写这个函数的方式,
q
更像输出参数而不是输入参数,实际上,函数创建 > a Table (带
table
),而不是要求太高。函数 Expr q =>表 - > q
。)
basal
有类型
basal ::(表 - > IO [JSON]) - > ScottyM()
basal ::(forall q.Expr q => q - > IO [JSON]) - > ScottyM()
无法推断(q〜Table)
错误。
rdb
会导致问题,但可能清除这个问题将会阻止问题发生。通常一旦你已经打破了类型系统,很难预测其在其他地方的行为。run' :: Expr query => RethinkDBHandle -> query -> IO [JSON]
rdb q = withResource pool (\h -> run' (use h $ db "test") q)
ReQL and Table
Expr
so they both accepted by GHC.ReQL
instead of Expr a
, then obveously it stops accepting Table
input and visa versa. Specifying input as Expr a
, which both ReQL
and Table
are instances of, stops with the error above. Dropping the signature all together works fine.main = do
pool <- createPool (connect "localhost" 28015 Nothing) close 1 300 5
let rdb q = withResource pool (\h -> run' (use h $ db "test") q)
scotty 3000 $ basal rdb
basal :: Expr q => (q -> IO [JSON]) -> ScottyM ()
basal r = get "/json" $ showJson r
showJson :: Expr q => (q -> IO [JSON]) -> ActionM ()
showJson r = do
j <- lift $ r $ table "mytable"
text $ T.pack $ show j
Main.hs:19:17:
No instance for (Expr q0) arising from a use of `basal'
The type variable `q0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Expr () -- Defined in `Database.RethinkDB.ReQL'
instance (Expr a, Expr b) => Expr (a, b)
-- Defined in `Database.RethinkDB.ReQL'
instance (Expr a, Expr b, Expr c) => Expr (a, b, c)
-- Defined in `Database.RethinkDB.ReQL'
...plus 24 others
In the second argument of `($)', namely `basal rdb'
In a stmt of a 'do' block: scotty 3000 $ basal rdb
In the expression:
do { pool <- createPool
(connect "localhost" 28015 Nothing) close 1 300 5;
let rdb q = withResource pool (\ h -> ...);
scotty 3000 $ basal rdb }
Main.hs:26:19:
Could not deduce (q ~ Table)
from the context (Expr q)
bound by the type signature for
showJson :: Expr q => (q -> IO [JSON]) -> ActionM ()
at Main.hs:24:13-52
`q' is a rigid type variable bound by
the type signature for
showJson :: Expr q => (q -> IO [JSON]) -> ActionM ()
at Main.hs:24:13
In the return type of a call of `table'
In the second argument of `($)', namely `table "mytable"'
In the second argument of `($)', namely `r $ table "mytable"'
showJson
is wrong.r
is being applied directly to table
which is table :: String -> Table
its type is not r :: Expr q => q -> IO [JSON]
r :: Table -> IO [JSON]
RankNTypes
)r :: forall q . Expr q => q -> IO [JSON]
fromJson
takes an input which it demands uses only the Expr
interface on its argument" instead of "fromJson
takes any kind of input which happens to use an Expr
instantiated type as its argument". For instance, with the type you've givenfromJson (undefined :: Query -> IO [JSON])
r
is being used in the function body.q
. Due to the way this function is written, q
acts more like an output argument than an input argument. Indeed, the function creates a Table
(with table
) instead of demanding one. The argument you've written thus implies that we have a function Expr q => Table -> q
.)basal
to have the typebasal :: (Table -> IO [JSON]) -> ScottyM ()
basal :: (forall q . Expr q => q -> IO [JSON]) -> ScottyM ()
Cannot deduce (q ~ Table)
error.
rdb
would lead to issues, but it may be that clearing this one will stop problems from occurring there. Usually once you've already broken the type system it's very hard to predict its behavior in other locations.