Haskell中模拟对象的身份 [英] Identity of simulation objects in Haskell

查看:122
本文介绍了Haskell中模拟对象的身份的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用面向对象的语言编写仿真程序,每个对象都有一个标识 - 也就是说,即使其他对象具有完全相同的属性,也可以将其与仿真中的每个其他对象进行区分。一个对象保留它的身份,不管它随着时间的推移而变化多少。这是因为每个对象在内存中都有唯一的位置,我们可以用指针或引用来表示该位置。即使您不强制使用GUID等附加身份系统,也可以使用此功能。 (你经常会这样做,以支持像网络或数据库这样的事情,而不是用指针来思考)。



我不相信有一个等价的概念哈斯克尔。那么,标准方法是使用类似GUID的方式吗?



更新以澄清问题:身份是我问题域中的一个重要概念出于一个原因:对象具有彼此的关系,并且必须保留这些关系。例如,Haskell通常会说一辆红色的车是一辆红色的车,而所有的红色车都是一样的(只有颜色是汽车唯一的属性)。但是如果每辆红色汽车都必须与其所有者挂钩呢?如果车主可以重漆汽车?

综合答案的最终更新:共识似乎应该只添加标识符数据类型如果模拟的某些部分实际上会使用这些标识符,并且没有其他方式来表达相同的信息。例如。对于一个人拥有多辆汽车的情况,每辆汽车都有一种颜色,一个人可以保留不可变的汽车列表。只要您有权访问该人,就完全表达了所有权关系。



个人可能需要也可能不需要某种唯一标识符。发生这种情况的一种情况是:有一个函数需要Car和所有Persons的集合,并在适当的Person上施加ParkingTicket。汽车的颜色不能唯一标识获得票证的人。所以我们可以给这个人一个ID并让Car存储它。



但是,即使这样做可以通过更好的设计来避免。也许我们的车现在有一个ParkingPosition类型的附加属性,可以评估为合法或非法。因此,我们将人员集合传递给一个函数,该函数查看每个人的汽车列表,检查每个人的ParkingPosition,并在适当的情况下将ParkingTicket强加给该人。因为这个函数总是知道它正在查看哪个人,所以没有必要让Car来记录这些信息。



所以在许多情况下,分配ID并不是必要的第一次看起来可能是这样。

解决方案

为什么你想解决这个非问题?对象标识是带有OO语言的一个问题,Haskell乐于避免。



在一个不可变对象的世界里,两个具有相同值的对象是同一个对象。把两个相同的不可变对象放到一个列表中,并且无论您想要如何看待事物(例如它们都有助于总数的元素,并且它们具有唯一索引),您都有两个不同的对象,而不存在任何问题Java风格的引用平等导致。如果你喜欢,你甚至可以将该列表保存到数据库表中,并获得两个不同的行。你还需要什么?

更新



Jarret,你好像是相信你的模型中的对象必须真正地分离身份,因为现实生活中的对象是不同的。但是,在模拟中 ,这只在需要区分对象的上下文中很重要。一般来说,您只需在必须区分和跟踪对象的环境中使用唯一标识符,而不是在这些环境之外。因此,识别这些上下文,将重要的对象的生命周期映射到您的模拟(而不是真实的世界),并创建适当的标识符。



您不断为自己的问题提供答案。如果汽车拥有车主,那么Bob的红色汽车可以与Carol的红色汽车区分开来。如果鲍勃可以重漆他的车,你可以用一辆蓝色的汽车替换他的红色汽车。您只需要更多,如果


  1. 您的模拟汽车没有车主

  2. 您需要能够在一个简单的模型中,1可以是真实的,2是不可以的。
  3. 在这种情况下,所有无主的红色汽车都是同一辆红色汽车所以为什么打扰使它们与众不同?



    在你的导弹模拟中,为什么导弹需要跟踪他们拥有的发射器?他们不是针对他们的发射器!如果发射装置在发射后可以继续控制导弹,那么发射装置需要知道它拥有哪种导弹,但反过来是不正确的。导弹只需要知道它的轨迹和目标。当它着陆和爆炸时,业主的意义何在?如果它是从启动器A启动而不是启动器B启动的话,它会发出更大的爆炸声吗? $ b 您的启动器可以是空的,或者它可以有 n 导弹仍然可用。它有一个位置。目标有地点。任何时候都有 k 飞行中的导弹;每个导弹都有一个位置,速度/弹道和爆炸力。任何位置与地面重合的导弹都应该转化为爆炸导弹,或者等等。

    在每种情况下,哪些信息很重要?发射器身份在爆炸时真的很重要吗?为什么?敌人是否会发动报复性袭击?没有?那么这对于爆炸并不重要。在发布之后,它可能甚至不是重要的信息。发射可以简单地说是属于发射器A的导弹数量减少而飞行中的导弹数量递增的步骤。现在,您可能会有一个很好的答案对这些问题,但你应该完全映射你的模型,然后开始使用它们可能不需要的身份对象化。


    Writing a simulation in an object-oriented language, each object has an identity--that is, a way to distinguish it from every other object in the simulation, even if other objects have the exact same attributes. An object retains its identity, no matter how much it changes over time. This is because each object has a unique location in memory, and we can express that location with pointers or references. This works even if you don't impose an additional identity system like GUIDs. (Which you would often do to support things like networking or databases which don't think in terms of pointers.)

    I don't believe there is an equivalent concept in Haskell. So, would the standard approach be to use something like GUIDs?

    Update to clarify the problem: Identity is an important concept in my problem domain for one reason: Objects have relationships to each other, and these must be preserved. For example, Haskell would normally say a red car is a red car, and all red cars are identical (provided color is the only attribute cars have). But what if each red car must be linked to its owner? And what if the owner can repaint his cars?

    Final update synthesizing the answers: The consensus seems to be that you should only add identifiers to data types if some part of the simulation will actually use those identifiers, and there's no other way to express the same information. E.g. for the case where a Person owns multiple Cars, each of which has a color, a Person can keep a list of immutable Cars. That fully expresses the ownership relationship as long as you have access to the Person.

    The Person may or may not need some kind of unique identifier. One scenario where this would occur is: There's a function that takes a Car and a collection of all Persons and imposes a ParkingTicket on the appropriate Person. The Car's color cannot uniquely identify the Person who gets the ticket. So we can give the Person an ID and have the Car store it.

    But even this could potentially be avoided with a better design. Perhaps our Cars now have an additional attribute of type ParkingPosition, which can be evaluated as legal or illegal. So we pass the collection of Persons to a function that looks at each Person's list of Cars, checks each one's ParkingPosition, and imposes the ParkingTicket on that Person if appropriate. Since this function always knows which Person it's looking at, there's no need for the Car to record that info.

    So in many cases, assigning IDs is not as necessary as it first may seem.

    解决方案

    Why do you want to "solve" this non-problem? Object identity is a problem with OO languages which Haskell happily avoids.

    In a world of immutable objects, two objects with identical values are the same object. Put the same immutable object twice into a list and you have two different objects wherever you want to see things that way (they "both" contribute to the total number of elements, for example, and they have unique indexes) without any of the problems that Java-style reference equality causes. You can even save that list to a database table and get two different rows, if you like. What more do you need?

    UPDATE

    Jarret, you seem to be convinced that the objects in your model must have genuinely separate identities just because real life ones would be distinct. However, in a simulation, this only matters in the contexts where the objects need to be differentiated. Generally, you only need unique identifiers in a context where objects must be differentiated and tracked, and not outside those contexts. So identify those contexts, map the lifecycle of an object that is important to your simulation (not to the "real" world), and create the appropriate identifiers.

    You keep providing answers to your own questions. If cars have owners, then Bob's red car can be distinguished from Carol's red car. If bob can repaint his car, you can replace his red car with a blue car. You only need more if

    1. Your simulation has cars without owners
    2. You need to be able to distinguish between one ownerless red car and another.

    In a simple model, 1 may be true and 2 not. In which case, all ownerless red cars are the same red car so why bother making them distinct?

    In your missile simulation, why do missiles need to track their owning launchers? They're not aimed at their launchers! If the launcher can continue to control the missile after it is launched, then the launcher needs to know which missiles it owns but the reverse is not true. The missile just needs to know its trajectory and target. When it lands and explodes, what is the significance of the owner? Will it make a bigger bang if it was launched from launcher A rather than launcher B?

    Your launcher can be empty or it can have n missiles still available to fire. It has a location. Targets have locations. At any one time there are k missiles in flight; each missile has a position, a velocity/trajectory and an explosive power. Any missile whose position is coincident with the ground should be transformed into an exploding missile, or a dud etc etc.

    In each of those contexts, which information is important? Is the launcher identity really important at detonation time? Why? Is the enemy going to launch a retaliatory strike? No? Then that's not important information for the detonation. It probably isn't even important information after launch. Launching can simply be a step where the number of missiles belonging to Launcher A is decremented while the number of missiles in flight is incremented.

    Now, you might have a good answer to these questions, but you should fully map your model before you start lumbering objects with identities they may not need.

    这篇关于Haskell中模拟对象的身份的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆