【发布时间】:2009-07-28 00:26:52
【问题描述】:
我在使用 haskell 的类时遇到问题。
基本上,我有一个算法(一种奇怪的图形遍历算法),它以一个容器作为输入,其中包括存储已经看到的节点(我热衷于避免单子,所以让我们继续. :))。问题是,该函数将容器作为参数,并且只调用一个函数:“set_contains”,它询问容器...是否包含节点 v。(如果您好奇,作为参数传入的另一个函数会实际的节点添加)。
基本上,我想尝试各种数据结构作为参数。然而,由于没有重载,我不能让多个数据结构与最重要的 contains 函数一起使用!
所以,我想做一个“Set”类(我不应该自己动手,我知道)。多亏了 Chris Okasaki 的书,我已经建立了一个非常漂亮的红黑树,现在剩下的只是创建 Set 类并将 RBT 等声明为它的实例。
下面是代码:
(注意:代码大量更新——例如,现在 contains 不调用辅助函数,而是类函数本身!)
data Color = Red | Black
data (Ord a) => RBT a = Leaf | Tree Color (RBT a) a (RBT a)
instance Show Color where
show Red = "r"
show Black = "b"
class Set t where
contains :: (Ord a) => t-> a-> Bool
-- I know this is nonesense, just showing it can compile.
instance (Ord a) => Eq (RBT a) where
Leaf == Leaf = True
(Tree _ _ x _) == (Tree _ _ y _) = x == y
instance (Ord a) => Set (RBT a) where
contains Leaf b = False
contains t@(Tree c l x r) b
| b == x = True
| b < x = contains l b
| otherwise = contains r b
注意我有一个非常愚蠢定义的 RBT Eq 实例。这是故意的 --- 我从 the gentle tutorial 复制它(但偷工减料)。
基本上,我的问题归结为:如果我注释掉 Set (RBT a) 的实例化语句,一切都会编译。如果我重新添加它,我会收到以下错误:
RBTree.hs:21:15:
Couldn't match expected type `a' against inferred type `a1'
`a' is a rigid type variable bound by
the type signature for `contains' at RBTree.hs:11:21
`a1' is a rigid type variable bound by
the instance declaration at RBTree.hs:18:14
In the second argument of `(==)', namely `x'
In a pattern guard for
the definition of `contains':
b == x
In the definition of `contains':
contains (t@(Tree c l x r)) b
| b == x = True
| b < x = contains l b
| otherwise = contains r b
而且我这辈子都无法弄清楚为什么这不起作用。 (附带说明一下,“contains”函数在别处定义,基本上具有 RBT 数据类型的实际 set_contains 逻辑。)
谢谢! - 阿戈尔
第三次修改:删除之前的修改,合并在上面。
【问题讨论】:
-
@Agor:容器在什么意义上是“多类型容器”?
-
@yairchu:我想这不是正确的标签,但我想不出更好的标签。我试图表达这样一个事实,当我试图制作一个类型为 t 的集合时,它包含一个不同的类型 a,这会导致问题。或者至少,那是,但这里的答案非常有帮助。 :) 无论如何,我同意我的标题有点笨拙,如果有更好的写法......
标签: class haskell functional-programming