2013-03-05 103 views
6

我有一个叫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" 

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

有什么想法?

在此先感谢。

回答

4

可以做到正是你想用你的最后一个实例与扩展什么:FlexibleInstancesUndecidableInstances

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

我不知道有什么办法做到这一点,没有任何扩展。但是,使用扩展并不是天生就不好,除非您将来可能要使用其他编译器。

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

instance Foo f => Bar f where ... 

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

+0

非常感谢!就我所知,“FlexibleInstance”是什么?这两个扩展是成对使用的吗? – phaazon 2013-03-05 09:46:18

+1

我始终围绕所有上下文编写括号。这使得类型签名和类/实例头更具可读性。所以我不同意你的风格。 – ertes 2013-03-05 10:05:31

+0

关于FlexibleInstaces:另请参阅本QA:http://stackoverflow.com/questions/8367423/are-haskell-flexibleinstances-a-stable-extension-to-the-language – scravy 2013-03-05 10:27:20

相关问题