【问题标题】:Cannot infer instance (haskell error)无法推断实例(haskell 错误)
【发布时间】:2014-07-01 05:33:30
【问题描述】:

我的作业中定义了以下内容:

type Rel a = Set (a,a)

complR :: Ord a => Set a -> Rel a -> Rel a
complR (Set xs) r = Set [(x,y) | x <- xs, y <- xs, not (inR r (x,y))]

集合类型可以这样调用,例如:(Set [(1,2)])。 当我尝试像这样调用函数时,我收到“无法推断实例”错误。我很确定这是因为我的电话和具体的 Rel a。 inR 也在作业中定义,我在这里没有包括在内。

我做错了什么?例如,我这样称呼它:

complR (Set [(5,4), (3,3)]) (Set [(1,3)])

谢谢!

编辑: 我不认为作业是使用 Data.Set。我不认为包括在内。我看到了数据列表。但是我确实看到了:newtype Set a = Set [a] deriving (Eq,Ord)。 inR 的类型是这样的:Ord a => Rel a -> (a,a) -> Bool。 此作业中使用的文件是http://www.cwi.nl/~jve/rcrh/REL.hshttp://www.cwi.nl/~jve/rcrh/SetOrd.hs

函数 complR 被放置在 REL.hs 文件中。 我调用 complR 时得到的错误是:

ERROR - Cannot infer instance
*** Instance   : Num (b,a)
*** Expression : complR (Set [(5,4),(3,3)]) (Set [(1,3)])

【问题讨论】:

  • 你在使用Data.Set吗?您可以发布您收到的确切错误消息吗? GHC 的错误消息通常非常有用,并且包含有助于诊断问题的上下文信息。可以包含inR 的类型吗?我认为它类似于inR :: Ord a =&gt; Rel a -&gt; (a, a) -&gt; Bool,但很难确定。
  • 它看起来好像你正在使用一些Set 实现,它被定义为只不过是data Set a = Set [a],这意味着使用Set 构造函数构造值,就像你所做的那样这里在complR 的右侧的定义将不能确保它返回一个真正的Set,这要求没有元素重复。这是否也在您的任务中为您定义?如果是这样,请包括Set 的定义,因为没有它很难弄清楚有什么问题。
  • 感谢您的评论!我不认为作业是使用 Data.Set。我不认为包括在内。我看到了数据列表。但是我确实看到了:newtype Set a = Set [a] deriving (Eq,Ord)。 inR 的类型是这样的:Ord a => Rel a -> (a,a) -> Bool (就像你说的那样)
  • @user3791741 bheklilr 是对的 - 到目前为止,您的所有相关代码都应该在您的问题中,包括从屏幕复制和粘贴的 exact 错误消息。
  • @user3791741 很好地提出了一个包含所有相关细节的问题。有一个赞成票和几个答案!

标签: haskell set relation


【解决方案1】:

这里的问题是你如何调用complR。您的定义也可能不是您想要的。仔细检查complR的类型:

complR :: Ord a => Set a -> Rel a -> Rel a

让我们代入Rel a = Set (a, a)的定义:

complR :: Ord a => Set a -> Set (a, a) -> Set (a, a)

现在,看看你是怎么称呼它的:

complR (Set [(4, 5), (3, 3)]) (Set [(1, 3)])

您是说第一个参数的类型为Num b =&gt; Set (b, b),这意味着a ~ Num b =&gt;(b, b),这意味着第二个参数的类型必须为Num b =&gt; Set ((b, b), (b, b))。由于您为此参数输入了Set [(1, 3)],它会尝试统一Num b =&gt; bNum b =&gt; (b, b) 类型,这会导致您在上面看到的错误。

你如何解决这个问题?您的选择是更改 complR 的定义,使其具有类型

complR :: Ord a => Rel a -> Rel a -> Rel a

或者修正你如何称呼它

complR (Set [3, 4, 5]) (Set [(1, 3)])

我不会告诉你在这种情况下哪个是正确的,你必须自己确定。


解决此类错误的一种方法是在代码中添加一些显式类型注释:

complR (Set [(5, 4), (3, 3)] :: Set (Int, Int)) (Set [(1, 3)] :: Rel Int)

会抛出错误(在 GHC 中)

Couldn't match type `Int' with `(Int, Int)'
Expected type: Rel (Int, Int)
  Actual type: Rel Int
In the second argument of `complR', namely
  `(Set [(1, 3)] :: Rel Int)'
In the expression:
  complR
    (Set [(5, 4), (3, 3)] :: Set (Int, Int)) (Set [(1, 3)] :: Rel Int)
In an equation for `it':
    it
      = complR
          (Set [(5, 4), (3, 3)] :: Set (Int, Int)) (Set [(1, 3)] :: Rel Int)

更明确地说“无法将类型 Int(Int, Int) 匹配”,这更清楚地表明了问题所在,您正在尝试在需要单个数字的地方使用元组。它甚至说“预期类型:Rel (Int, Int) ... 在complR 的第二个参数中”,它告诉你有什么事情发生了。


作为旁注,我强烈建议放弃 Hugs 以支持 GHC。您将获得更多信息丰富的错误消息,以及更多功能。 Hugs 自 2006 年以来一直没有开发,而 GHC 仍在积极开发中并定期发布新版本。 Hugs 也有一些不时出现的错误,因为它已经 8 年没有进行任何维护,所以你最好抓住 Haskell Platform,其中包括 GHC 和许多流行的库。

【讨论】:

  • 你的答案在各方面都比我的好,除了我不同意初学者应该使用 ghc 而不是拥抱。当出现问题时,Hugs 通常 会更好地为您提供类型不匹配错误而不是“No instance for...”错误,这是一个令人惊讶的示例,它未能发现参数不正确,而是比缺少类型类。当您刚开始时,您可能不需要超越 Haskell 98(稳定的教学和教科书基础是 Haskell 98 的设计目标之一)。
  • 非常感谢!真的很有帮助!我很欣赏你的回答和其他人。现在很清楚,现在对我来说实际上也很有意义!就像我在下面的评论中所说的那样,我真的很感谢人们在这里帮助 Haskell。我怕我得不到任何答复。再次感谢您!
  • @AndrewC 我同意 Hugs 有更多用户友好的错误消息,但是当一个新手突然发现他们需要只有 Haskell2010 提供的功能时,他们现在必须改变他们的工具链并习惯这些现在更复杂的错误消息。在我看来,最好从更难(但信息更丰富)的错误消息开始,这样您就可以尽快熟悉它们。
  • @user3791741 实际上我想说我们在 Haskell 标签上有一个非常活跃的社区。您甚至会在这里遇到大人物,例如撰写Real World Haskell 的唐·斯图尔特,看到他回答有关他的书的问题并不少见。整个 Haskell 社区中还有很多其他活跃的人,因此您通常可以获得非常高质量的答案。
  • 通常可能,但“Missing instance for...”在 99% 的情况下都是误诊。缺少实例的更好错误消息可能包含:“类型不匹配。 (5,4) :: (Num a,Num b) =&gt; (a,b)3 :: Num c =&gt; c 的类型不匹配。可能的修复:1. 检查您是否提供以正确的顺序将正确的参数与正确的类型传递给complR :: Ord a =&gt; Set a -&gt; Rel a -&gt; Rel a2. 检查您是否需要 Num (a,b) 的实例。"我很乐意留下缺席的实例消息。毕竟,如果你得到Num a =&gt; aComplex 之间的类型不匹配,那就很清楚了。
【解决方案2】:

你有type Rel a = Set (a,a)complR 的类型签名是

complR :: Ord a => Set a -> Rel a -> Rel a

所以我们应该给它一组a,一组as,它会给我们一组新的对。

你试过了

complR (Set [(5,4), (3,3)]) (Set [(4,5)])

这实际上是一个类型不匹配,因为两者都是第一个应该只是一个集合的关系,但是编译器好心(!)试图离开并弄清楚你是否可以制作一些奇怪的 Num 实例会使所有类型加起来,但它不能。

【讨论】:

  • 非常感谢您的回答。不幸的是,我不能接受两个答案(绿色按钮)。我选择了你上面的评论。但是请注意,您的 cmets 也非常有帮助,我非常感谢有人这样做!继续努力。
  • @user3791741 别担心。我也会选择 bheklilr 的答案而不是我的答案!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-28
相关资源
最近更新 更多