Haskell 类型类检查
我想使用haskell来实现游戏,并想使用类型类系统来实现项目系统。它会像这样工作:
data Wood = Wood Int
instance Item Wood where
image a = "wood.png"
displayName a = "Wood"
instance Flammable Wood where
burn (Wood health) | health' <= 0 = Ash
| otherwise = Wood health'
where health' = health - 100
其中 Item 和 Flammable 类是这样的:
class Item a where
image :: a -> String
displayName :: a -> String
class Flammable a where
burn :: (Item b) => a -> b
为此,我需要一种方法来检测值是否是类型类的实例。
Data.Data 模块提供了类似的功能,因此我相信这是可能的。
I would like to use haskell to implement a game, and would like to use a system of type classes to implement the item system. It would work something like this:
data Wood = Wood Int
instance Item Wood where
image a = "wood.png"
displayName a = "Wood"
instance Flammable Wood where
burn (Wood health) | health' <= 0 = Ash
| otherwise = Wood health'
where health' = health - 100
where the Item and Flammable classes are something like this:
class Item a where
image :: a -> String
displayName :: a -> String
class Flammable a where
burn :: (Item b) => a -> b
To do this, I would need a way to detect whether a value is an instance of a type class.
The Data.Data module gives a similar functionality so that leads me to believe that this is possible.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
类型类可能是错误的方法。考虑使用普通代数数据类型,例如:
如果这使得添加新项目变得太困难,您可以改为在数据类型本身中对操作进行编码。
然而,这使得添加新功能变得更加困难。同时执行这两项操作的问题称为表达式问题。有一个 Ralf Lämmel 博士在第 9 频道的精彩讲座,他更深入地解释了这个问题并讨论了各种非解决方案,如果您有以下问题,非常值得观看 时间。
有多种方法可以解决这个问题,但它们比我所演示的两种设计要复杂得多,因此我建议使用其中一种(如果它符合您的需求),并且除非必须,否则不要担心表达问题。
Type classes are probably the wrong way to go here. Consider using plain algebraic data types instead, for example:
If this makes it too hard to add new items, you can instead encode the operations in the data type itself.
However, this makes it harder to add new functions. The problem of doing both at the same time is known as the expression problem. There is a nice lecture on Channel 9 by Dr. Ralf Lämmel where he explains this problem more in depth and discusses various non-solutions, well worth the watch if you have time.
There are approaches to solving it, but they are considerably more complex than the two designs I've illustrated, so I recommend using one of those if it fits your needs, and not worrying about the expression problem unless you have to.
问题是:
这意味着
burn
的结果值必须是多态。它必须能够填充Item
的任何实例的任何漏洞。现在,很明显你正在尝试编写类似这样的东西(用具有接口和子类化的想象的 OO 语言):
在这种代码中,你说
burn
将产生一些 物品,但不保证它是什么类型的物品。这就是“对于所有人”和“存在”之间的区别。你在Haskell代码中想要表达的是“存在”,但实际上表达的是“对于所有人”。现在,如果您确实确定要执行“存在”功能,则可以查看使用存在类型。但要小心。如果您计划编写这样的代码:
那么您几乎肯定做错了,并且会遇到很多痛苦和痛苦。相反,请考虑哈马尔建议的替代方案。
Here's the problem:
What this means is that the result value of
burn
must be polymorphic. It must be able to fill any hole for any instance ofItem
.Now, it's quite apparent you're trying to write something like this (in imaginary OO language with interfaces and subclassing):
In this sort of code, you're saying that
burn
will produce some item, without any guarantees about what kind of item it is. This is the difference between "for all" and "there exists". What you wanted to express in the Haskell code was "there exists", but what you actually expressed was "for all".Now if you're really sure you want to do "there exists" functionality, you can take a look at using Existential Types. But beware. If you are planning on writing code like this:
Then you are almost certainly doing it wrong, and will run into much pain and agony. Instead consider hammar's suggested alternatives.