8

我有一个Foo拥有一个函数的类gen :: Int -> [Foo]。例如,我可以制作一个这样的实例Foo

data FooTest = FooTest Int

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

现在,让我们假设我有另一个Bar定义了 function 的类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"

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

任何想法?

提前致谢。

4

1 回答 1

4

您可以使用带有两个扩展名的最后一个实例完全完成您想要的操作:FlexibleInstancesUndecidableInstances.

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

我不知道有任何方法可以在没有任何扩展的情况下做到这一点。但是,除非您将来可能想使用其他编译器,否则使用扩展本身并不是坏事。

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

instance Foo f => Bar f where ...

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

于 2013-03-05T09:33:08.663 回答