我有一个类型的类GHC:为什么输入歧义走开使用让
class (Monad f) => Test f where
test ::() -> f()
和实例
instance Test (ErrorT String (Identity)) where
test pat = return pat
如果我运行一个单子栈参照本实例时,GHC可以”找不到什么单子我说的(在Either String
单子的do
块):
rhs' <- runIdentity $ runErrorT $ test rhs
产生的错误信息:
Ambiguous type variable `f0' in the constraint:
(Test f0) arising from a use of `test'
...
但是,如果我的部分test rhs
绑定到一个变量:
let action = test rhs
rhs' <- runIdentity $ runErrorT $ action
它的工作原理,即使变量不能用于其他地方所以没有什么新的可以推断一下。
这是怎么可能的,如果我没有添加类型检查器使用的信息?为什么不能找出相应的第一个公式的类型?或者这两个公式不相等? Haskell类型检查器的哪个部分(或者desugaring规则?)在这里我不理解?
我使用的扩展MultiParamTypeClasses
,FlexibleInstances
和ScopedTypeVariables
编辑:我简单的例子,从而出现奇怪的问题,而不需要我的代码的其余部分(以及更短的单子栈),但现在它看起来荒谬。该语句的完整的上下文是:
doStuff :: (Map Int()) -> Either String (Map Int())
doStuff g = run (snd . head . Map.toList $ g) g where
run ::() -> Map Int() -> Either String (Map Int())
run rhs g = do
let action = test rhs
rhs' <- runIdentity $ runErrorT $ test rhs -- or: action
return g
你能把这个减少到一个小的可重复的例子吗?这个代码中有太多的外部事物可以自己尝试 - 例如'Pattern','Symbol','g'和'rhs'。 – 2014-10-04 17:43:34
我认为在你的cutdown代码中,如果你不使用'action',那么'let action = test rhs'就会产生歧义。如果我使用'test rhs'并且删除'let action ='行,它编译得很好。 – 2014-10-04 18:34:17
另外,假设这不是你原来的代码的问题,如果你不使用'$',即写'runIdentity(runErrorT(test rhs))'',会发生什么?这只是一个猜测,但在某些时候,有一些有趣的规则可以帮助'运行'...'类型检查,这只是可能的。 – 2014-10-04 18:39:10