我见过几篇有类似主题的帖子,但它们并不能真正帮助我解决问题。所以我敢重复。
现在我有了一个有签名的函数:
run' :: Expr query => RethinkDBHandle -> query -> IO [JSON]这是一个数据库查询运行函数。
我将此函数封装在一个池中(池已经创建,与问题无关),以简化连接。
rdb q = withResource pool (\h -> run' (use h $ db "test") q)从本质上讲,此函数具有与上面运行的完全相同的签名。
问题是,如果我在没有签名的情况下使用这个函数,那么一切都是好的,而GHC很乐意解决问题。一旦我指定了签名,它就停止了对某些输入的工作,抱怨无法推断类型。
主要有两种输入类型用作查询输入。
ReQL and Table这两种类型都是Expr的实例,因此它们都被GHC所接受。
一旦我把签名,一切停止工作,GHC共平原,关于不能推断类型,并给我“刚性类型变量绑定类型签名”错误。如果我让签名变得更具体,比如ReQL而不是Expr a,那么它就会停止接受Table输入,而visa相反。将输入指定为Expr a ( ReQL和Table都是它们的实例),在上面的错误中停止。把签名全部删除,效果很好。
那我该怎么解决呢?放弃签名感觉不对。
我不知道是否应该使这个问题更通用或更具体,但如果有帮助,这是一个包含所有类型和实例以帮助提供建议的库。
再思考DB
更新
根据请求,这是生成错误的完整代码列表。
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"'谢谢
发布于 2014-04-01 13:29:31
读取错误消息的第一个问题似乎是您为showJson指定的类型是错误的。
由于r直接应用于table (即table :: String -> Table ),所以它的类型不是
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])也会统一..。但是很明显,这就是在函数体中使用r的方式。
(特别是,它与参数q的正性有关。由于这个函数的编写方式,q的作用更像是输出参数,而不是输入参数。实际上,该函数创建了一个Table (使用table),而不是需要一个。因此,您编写的参数意味着我们有一个函数Expr q => Table -> q。)
现在,这种类型的特异性也向上传播,导致basal具有该类型。
basal :: (Table -> IO [JSON]) -> ScottyM ()或
basal :: (forall q . Expr q => q -> IO [JSON]) -> ScottyM ()从而导致Cannot deduce (q ~ Table)错误。
在这一点上,我不知道为什么为rdb声明一个显式类型会导致问题,但可能是清除这个类型会阻止问题的发生。通常,一旦你已经打破了类型系统,很难预测它在其他地方的行为。
https://stackoverflow.com/questions/22778098
复制相似问题