haskell - GHC : Why does type ambiguity go away when using let

标签 haskell typechecking

我有一个类型类

class (Monad f) => Test f where
  test :: () -> f ()

和一个实例

instance Test (ErrorT String (Identity)) where
  test pat = return pat

如果我运行引用此实例的 monad 堆栈,GHC 无法找出我正在谈论的 monad(在 Either String monad 的 do block 中) ):

rhs' <- runIdentity $ runErrorT $ test rhs

产生错误消息:

Ambiguous type variable `f0' in the constraint:
  (Test f0) arising from a use of `test'
  ...

但是如果我将 test rhs 部分绑定(bind)到变量:

let action = test rhs
rhs' <- runIdentity $ runErrorT $ action

它有效,即使该变量没有在其他地方使用,因此无法推断出任何新内容。

如果我没有添加类型检查器要使用的信息,这怎么可能?为什么它无法找出等效的第一个公式的类型?或者这两个公式不等价? Haskell 类型检查器(或脱糖规则?)的哪一部分我不明白?

我正在使用扩展 MultiParamTypeClassesFlexibleInstancesScopedTypeVariables

编辑:我简化了示例,因此奇怪的问题发生时不需要我的代码的其余部分(并且具有更短的单子(monad)堆栈),但现在它看起来毫无意义。该声明的完整上下文是:

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

最佳答案

代码

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
  rhs' <- runIdentity $ runErrorT $  test rhs
  return g

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 $ action
  return g

类型检查应该没有问题。问题是

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 $ action
  return g

原因是您似乎启用了 MonoLocalBinds 或单态限制,这会阻止绑定(bind)到 action 的泛化,除非类型已知。

关于haskell - GHC : Why does type ambiguity go away when using let,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26195242/

相关文章:

Haskell IO 递归

Groovy 的 @TypeChecked 或 @Builder + IntelliJ IDEA = false 错误提示。这是一个错误吗?

java - 匹配捕获与上限时类型检查中断?

typescript - 如果创建库,我应该手动验证 TypeScript 中的参数吗?

haskell - Haskell 中的 ViewPatterns 和多次调用

haskell - 修复一个特别模糊的 Haskell 空间泄漏

haskell - Haskell `seq` 算子的时间成本

haskell - Haskell 如何将整数文字转换为不同类型?

python-3.x - 如何让 mypy 提示将 Any 分配给 int

python - 检查函数参数类型是 Pythonic 吗?