在Haskell中表示的OO类

Kon*_*nos 1 oop haskell

H!

假设我有一个抽象类机器人,有几个属性,如'position'和'weight'.这个抽象类实现了三个方法:'take','drop'和'move',但也有一个抽象方法'makeAction'.然后我有两个名为'TRobot'和'FRobot'的子机器人.基本上,TRobot和FRobot将实现'makeAction'方法,但不会重新实现'take','drop'和'move'.

我的问题是你如何在Haskell中做到这一点.

我从数据类型开始:

data Robot = Robot {position :: Char, weight :: Int}
Run Code Online (Sandbox Code Playgroud)


编辑:

但我想函数'take','move'和'drop'(take :: Box - > Robot - > Robot)如果Robot是TRobot或FRobot则表现相同.

但是,功能

makeAction :: Robot -> Action
Run Code Online (Sandbox Code Playgroud)

无论Robot是TRobot还是FRobot都应该有不同的实现.

谢谢您的帮助.

Mat*_*hid 15

我有<在这里插入面向对象的设计>.如何在非OO语言(如Haskell)中实现它?

呃......这不是一个好主意.这很可能是远不如退后一步并解释什么你实际上是试图实现.Haskell需要一种完全不同的思考软件设计的方式.在不知道你真正想做什么的情况下,很难确切地知道实现它的最佳方式是什么.

特别是:两种机器人实际上有何不同?它们如何相似?

可能是您只想构建单个数据类型的构造函数(如您所编写的),其中每个move函数的行为都不同,而take/ drop不关心的函数.或者你可能只想要一个构造函数,其中一个字段可以说明它是哪种机器人类型.或许你真的想要两个完全独立的类型.如果不了解更多关于你想要做什么的话,很难说.

  • 我的观点确实是当初学者出现并开始询问如何在Haskell中进行OOP时,正确的反应是"学习Haskell方式".学习如何将外国概念编码成语言似乎就像在你走路之前试图跑. (5认同)
  • @DavidYoung我的观点仅仅是Haskell不是_designed_来支持OOP,而且在Haskell中编写代码时,根据对象和类进行思考不应该是起点.我同意这些概念可以编码,也许比较好.但这并不意味着它是解决编程问题的最佳方法. (2认同)

Die*_*Epp 7

在Haskell 中有很多方法可以做到这一点,但是你必须首先理解传统的"类"并不直接对应于任何Haskell结构.

你可以很容易地做这样的事情:

data Robot = Robot {
    position :: Char,
    weight :: Int,
    makeAction :: Robot -> String
}
Run Code Online (Sandbox Code Playgroud)

这里makeAction是包含不同函数TRobotFRobot类型的字段.有很多更复杂的方法可以做到,比如类型类,GADT,组合等等,但这会让你开始.

输入类版本

这是一种不同的方式,这更复杂.

这是一个普通的类型版本:

-- The robot type is expressed using a type parameter (called "a")
data Robot a = Robot {
    position :: Char,
    weight :: Int
}

-- All robot types have their own "makeAction" function
class RobotType a where
    makeAction :: Robot a -> String

data TRobot
instance RobotType TRobot where
    makeAction robot = ...

data FRobot
instance RobotType FRobot where
    makeAction robot = …
Run Code Online (Sandbox Code Playgroud)

请注意,Robot TRobotRobot FRobot不同的类型,所以如果你需要一个通用的机器人类型,你有存在类型做:

data AnyRobot = forall a. RobotType a => AnyRobot (Robot a)
Run Code Online (Sandbox Code Playgroud)

基本上,因为我们在类型系统中存储TRobot和FRobot之间的差异,我们需要存在类型以允许我们在运行时访问这些差异(因为类型在编译时被删除).

  • 有了这种方法,你就不会; 你只需要`makeFRobot`和`makeTRobot`函数来初始化具有不同`makeAction`函数的机器人. (2认同)