让一个类成为另一个类的实例
问题描述:
我有一个叫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
和UndecidableInstances
。
就像名称所暗示的那样,第二个扩展允许您编写不会终止的实例。这可能导致编译时无限循环;然而,这个实现在某个递归深度被任意限制,所以你不应该有实际无限的编译时间。
我不知道有什么办法做到这一点,没有任何扩展。但是,使用扩展并不是天生就不好,除非您将来可能要使用其他编译器。
此外,随机样式注:如果您只有一个约束,括号是可选的。所以你可以这样写:
instance Foo f => Bar f where ...
这不是很重要,但我认为第二个版本看起来更好。
非常感谢!就我所知,“FlexibleInstance”是什么?这两个扩展是成对使用的吗? – phaazon 2013-03-05 09:46:18
我始终围绕所有上下文编写括号。这使得类型签名和类/实例头更具可读性。所以我不同意你的风格。 – ertes 2013-03-05 10:05:31
关于FlexibleInstaces:另请参阅本QA:http://*.com/questions/8367423/are-haskell-flexibleinstances-a-stable-extension-to-the-language – scravy 2013-03-05 10:27:20