【问题标题】:What does this 'Ambiguous type variable `a` in the constraint' mean?这个“约束中的歧义类型变量‘a’”是什么意思?
【发布时间】:2012-01-11 22:54:42
【问题描述】:

在这段代码中,我试图让工作函数go 中的第一个参数成为“类型族”类型。我看到在type families documentation 类型中,类似的insert 函数属于类型类,而在下面的示例中它不属于。

我是类型族的新手,所以也许我用错了,但是这个错误是什么意思?

{-# LANGUAGE TypeFamilies #-}

-- | key
class K a where
  -- | iterator for key
  type I a :: *
  mkI :: a -> I a

--| A map
data (K a) => M a b = M a b

insert :: (K a) => a -> b -> M a b -> M a b
insert = go mkI    -- <<< PROBLEM
  where
    go o a b m = m

约束中的模糊类型变量“a”:

`K a'

  arising from an expression type signature at Data/Map2.hs:167:10-33

可能的修复:添加修复的类型签名 这些类型变量

【问题讨论】:

  • 首先,请注意数据类型上下文 (data (K a) =&gt; M a b = M a b) 已从语言中删除,并且从未有用过。现在看看其他的东西。

标签: haskell type-families


【解决方案1】:

这样编译:

{-# LANGUAGE TypeFamilies, GADTs, ScopedTypeVariables #-}

-- | key
class K a where
  -- | iterator for key
  type I a :: *
  mkI :: a -> I a

-- | A map
data M x y where
    M :: K a => a -> b -> M a b

insert :: forall a b. (K a) => a -> b -> M a b -> M a b
insert = go mkI
  where
    go :: (a -> I a) -> a -> b -> M a b -> M a b
    go o a b m = m

我改变了什么?为什么?

首先,我假设您想要M 上的约束,所以我使用了一种类型定义形式来强制约束并使其在使用站点上可用,即GADT

其次,您的 GHC 抱怨的问题是模棱两可。关键是编译器无法推断它应该使用 which mkI,所以我们必须告诉它。为此,我们必须将使用的类型变量带入作用域,然后在本地签名中告诉编译器要使用哪个类型实例。

【讨论】:

  • 您好,您如何使“go”成为顶级功能?
  • @cdupont 您可以将其移至顶层并将约束添加到类型签名go :: (K a) =&gt; (a -&gt; I a) -&gt; a -&gt; b -&gt; M a b -&gt; M a b。不过,我看不出这有什么用处。
  • 在这种情况下insert 中的abgo 中会有所不同...这就是您添加forall no 的原因?
  • @cdupont 从insert 传递的参数将确定使用的ab 类型。 forall 是在insert 范围内引用这些类型所必需的。在顶层,类型签名中的类型独立于insert 的类型,但参数的传递将确保go 的被调用实例使用相同的类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-15
  • 2017-05-25
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多