使类成为另一个类的实例

时间:2013-03-05 09:22:55

标签: class haskell instance

我有一个名为Foo的类,它拥有一个函数gen :: Int -> [Foo]。例如,我可以通过这种方式创建Foo的实例:

data FooTest = FooTest Int

instance Foo FooTest where
  gen n = replicate n (FooTest 0)

现在,让我们假设我有另一个名为Bar的类,它定义了一个函数bar :: Bar -> IO ()Foo的每个实例都必须是Bar的实例,但是 Bar实现对于每个实例都是完全相同的。这是一个例子:

class Foo f where
  gen :: Int -> [f]

class Bar b where
  bar :: b -> IO ()

instance Bar Foo where -- obviously that doesn’t work
  bar _ = putStrLn "bar through any Foo instance"

instance (Foo f) => Bar f where -- this needs the FlexibleInstance GHC extension first, then it still throws shit saying that the constraint is not smaller that I don’t shit
  bar _ = putStrLn "bar through any Foo instance"

这里的问题是我找不到任何方法使一个类成为另一个的实例,提到第一个类的任何实例将共享相同的实现以实现其他类的实例化。

有什么想法吗?

提前致谢。

1 个答案:

答案 0 :(得分:4)

使用两个扩展程序FlexibleInstancesUndecidableInstances,您可以使用上一个实例准确完成所需内容。

就像名称所暗示的那样,第二个扩展允许您编写不终止的实例。这可能会在编译时导致无限循环;但是,实现在某个递归深度任意上限,所以你不应该有无限的编译时间。

我根本不知道有什么方法可以做到这一点。但是,除非您可能希望将来使用其他编译器,否则使用扩展本身并不是很糟糕。

另外,随机样式注释:如果您只有一个约束,则括号是可选的。所以你可以把它写成:

instance Foo f => Bar f where ...

这不是很重要,但我认为第二个版本看起来更好。