Class 使一个类成为另一个类的实例

Class 使一个类成为另一个类的实例,class,haskell,instance,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

我有一个名为
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"
这里的问题是,我找不到任何方法使一个类成为另一个类的实例,更不用说第一个类的任何实例都将共享同一个实现来实例化另一个类

有什么想法吗


提前感谢。

使用上一个实例,您可以通过两个扩展实现您想要的功能:
FlexibleInstances
undedicatableinstances

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

如果没有任何扩展,我不知道有什么方法可以做到这一点。但是,使用扩展本身并不坏,除非您将来可能想使用其他编译器

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

instance Foo f => Bar f where ...

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

非常感谢!就我所知,
FlexibleInstance
的作用是什么?这两个扩展是否成对工作?我总是在所有上下文中使用括号。这使得类型签名和类/实例头更具可读性。因此,我不同意您的风格说明。关于FlexibleInstances:另请参见本QA: