我需要帮助将OO概念转换为Haskell.
想象一Vehicle类和Car和Truck亚类,具有driveOneMile一个返回双表示使用的总燃料的方法.每次调用driveOneMile也会改变车辆的内部状态.
这是我到目前为止在Haskell中所做的事情(因为在Haskell中没有实例变量,似乎我必须创建自己的"状态"类型):
type CarState = (Double,Double)
initialCarState = (0,0)
driveCarOneMile :: CarState -> (Double,CarState) --Double: total fuel used
driveCarOneMile s = ...
--the internal state of trucks is more complex. needs three Doubles
type TruckState = (Double,Double,Double)
initialTruckState = (0,0,0)
driveTruckOneMile :: TruckState -> (Double,TruckState)
driveTruckOneMile s = ...
Run Code Online (Sandbox Code Playgroud)
以类似的方式,我可以构建其他车辆及其"驱动"功能.
这就是我开车两次的方式:
fuelFor2Miles = fst $ driveCarOneMile $ snd $ driveCarOneMile initialCarState
Run Code Online (Sandbox Code Playgroud)
Haskell中的类与OO类完全不同,并且使用它们就像在大多数情况下编写OO代码一样,使事情变得比它们应该更复杂.特别是,一旦你开始考虑以"OO"的形式"收集许多汽车,卡车和其他车辆的集合",你就可以直接沿着兔子洞(正如Haskell Antipattern:Existential Typeclass所指出的那样).
您可能根本不需要一个班级来模拟您的不同类型的车辆.你可以定义
data Vehicle = Car CarState | Truck TruckState
Run Code Online (Sandbox Code Playgroud)
然后
driveOneMile :: Vehicle -> (Double, Vehicle)
Run Code Online (Sandbox Code Playgroud)
使用模式匹配来区分不同的车辆.
即使你真的需要更像类的东西(例如你正在编写一个库并希望用户提供自己的车辆),这并不一定意味着你需要异构集合.您可以给出Vehicle一个构造函数并向其中添加与类方法相对应的字段,以便该类成为一个类型,并且类实例成为值(这是反模式文章所倡导的方法).您可能还有一个Vehicle带有toGeneralVehicle :: a -> GeneralVehicle方法的类,并且具有根据GeneralVehicle类型定义的通用行为.
PS:签名背后的想法TruckState -> (Double,TruckState)是声音.事实上,我会说你不小心发现了这种State类型!State只是一个方便的抽象,使状态传递管道隐含.如果您很好奇,请查找有关Statemonad的问题和教程.
| 归档时间: |
|
| 查看次数: |
231 次 |
| 最近记录: |