关于Scala中类型类的问题
假设有类 Fruit
、Orange
和 Apple
。
abstract class Fruit
class Orange extends Fruit
class Apple extends Fruit
现在我想为 Orange
和 Apple
类型添加 write
功能。使用 type class 模式,我可以执行以下操作:
trait Writer[T] {def write(t:T)}
implicit object AppleWriter extends Writer[Apple] {
def write(a:Apple) {println("I am an apple!")}
}
implicit object OrangeWriter extends Writer[Orange] {
def write(o:Orange) {println("I am an orange!")}
}
def write[T](t:T)(implicit w:Writer[T]){w.write(t)}
所以,很好,但是如果我想定义 writeFruits
呢?
def writeFruits(fruits:List[Fruit]) {for (fruit <- fruits) write(fruit)}
我希望 writeFruits
为每个 fruit
调用 write[Apple]
或 write[Orange]
。我发现它不起作用(我知道为什么),但是也许我无论如何都可以实现writeFruits
。
我可以以某种方式实现 writeFruits 吗?
Let there are classes Fruit
, Orange
, and Apple
.
abstract class Fruit
class Orange extends Fruit
class Apple extends Fruit
Now I want to add write
functionality to both types Orange
and Apple
. Using the type class pattern I can do the following:
trait Writer[T] {def write(t:T)}
implicit object AppleWriter extends Writer[Apple] {
def write(a:Apple) {println("I am an apple!")}
}
implicit object OrangeWriter extends Writer[Orange] {
def write(o:Orange) {println("I am an orange!")}
}
def write[T](t:T)(implicit w:Writer[T]){w.write(t)}
So for, so good but what if I want to define writeFruits
?
def writeFruits(fruits:List[Fruit]) {for (fruit <- fruits) write(fruit)}
I would like writeFruits
to call either write[Apple]
or write[Orange]
for each fruit
. I see that it does not work (and I know why) but maybe I can implement the writeFruits
anyway.
Can I implement writeFruits
somehow ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在协变/逆变类型的实例中,您几乎需要在此处的“基”类型上定义类型类:
您还可以定义具有方差的类型类,以便在需要 Writer 时可以使用 Writer[Fruit] [苹果]。不幸的是,如果您想使用面向对象的多态性,则必须将其编码到功能方面。
*强文本*另一种选择是使用 HList 来写入水果并自己执行所有类型递归...
假设:
然后我们可以做一些有趣的事情,例如:
现在
注意:我还没有测试过这段代码,但是递归跨越类型的概念是合理的。我实际上并不推荐这种方法。
In the instance of covariant/contravariant types, you almost need to define your type class on the "base" type here:
You could also work on defining the type class with variance so that Writer[Fruit] could be used when you need a Writer[Apple]. It's unfortunate, but if you want to use OO polymorphism, you have to encode that into the functional aspects.
*strong text*Another option is to use an HList for write-fruits and do all the type-recursion yourself...
Assuming:
Then we can do something fun like:
NOW
Note: I have not tested this code, but the concept of recursively spanning types is sound. I'm not actually recommending this approach.
您只需挑选出存在
Writer
的那些Fruit
。不幸的是,一旦你转换为Fruit
,你就失去了自动辨别哪个是哪个的能力。如果您必须以这种方式设置问题,而不是组装可写水果列表或类似的列表,那么一个合理的选择是使用 FruitWriter 再次拆分类型:You need to pick out only those
Fruit
for which aWriter
exists. Unfortunately, once you've cast toFruit
you've lost the ability to automatically figure out which is which. If you must set up the problem this way--rather than assembling a list of writable fruit or somesuch--then one reasonable option is to split out the types again with aFruitWriter
:或者也许案例课程适合您?
Or maybe case-classes are for you?
这并不完全是您想要的,但给您很大的自由来构建您的层次结构:
如您所见,您可以拥有始终附加一个
Writer
的Fruit
(此处是Orange
),您可以“即时”附加 Writers(List
中的最后一个Apple
)。This is not exactly what you want, but gives you a lot of freedom to build your hiearchy:
As you can see, you can have
Fruit
s which have always aWriter
attached (hereOrange
s) and you can attach Writers "on the fly" (the lastApple
in theList
).