尽管有这个标题,我不会仅仅询问 OO 世界和 Haskell 之间的翻译,但我想不出更好的标题。此讨论类似于但不等于this one https://stackoverflow.com/questions/5474171/oo-interface-translation-to-haskell.
我开始了一个玩具项目,只是为了在阅读“Learn You a Haskell for a Great Good”时扩展我对 Haskell 的有限知识,并且我决定实现一个非常基本的“元素类型系统”,它是《最终幻想》等游戏中的典型战斗系统。
我跳过了大部分细节,但这简而言之是我的问题:
我想模拟一个咒语,一种可以对玩家或怪物施放的魔法。在面向对象的世界中,您通常会使用带有“onCast(Player)”方法的“Castable”接口,一个“Spell”类,这样您就可以定义这样的东西
Spell myNewSpell = Spell("Fire", 100, 20);
myNewSpell.onCast(Player p); //models the behaviour for the Fire spell
在 Haskell 中,我从类型和类的角度思考这一点(我知道 Haskell 中的类是一个不同的概念!)。我遇到了一些困难,因为我的第一次尝试是创建这个:
--A type synonim, a tuple (HP,MP)
type CastResult = (Integer,Integer)
--A castable spell can either deal damage (or restore) or
--inflict a status
class Castable s where
onCast :: s -> Either (Maybe Status) CastResult
data Spell = Spell{spellName :: String,
spellCost :: Integer,
spellHpDmg :: Integer,
spellMpDmg :: Integer,
spellElem :: Maybe Element} deriving (Eq,Show,Read)
现在假设我使用记录语法创建一些咒语
bio = Spell{spellName = "Bio", ...etc..}
我希望能够做这样的事情
instance Castable bio where
onCast bio = Left (Just Poison)
这里有很多问题:
-
我不能做“Castable bio”,因为 bio 必须是具体类型,而不是类型的值(它应该是 Castable Spell)
-
bio 不在范围内,在实例块内被视为模式匹配的值
总的来说,我觉得这种设计选择相当糟糕,但我仍在学习,我不掌握像函子这样的高级主题,仅举一例。
简而言之,处理这种情况的惯用方法是什么?我的意思是需要“一个定义,多个实例的多个实现”的情况,只是使用面向对象的术语。