Safe Haskell | None |
---|

Here we use `dynamic-object`

to descibe the concept of point-like particles from
classical mechanics. Also read the HSpec tests :
https://github.com/nushio3/dynamic-object/blob/master/test/ObjectSpec.hs
for more details.

- data Vec a = Vec a a
- data Mass = Mass
- data Velocity = Velocity
- data Momentum = Momentum
- data KineticEnergy = KineticEnergy
- mass :: MemberLens o Mass
- velocity :: MemberLens o Velocity
- momentum :: (UseReal o, Fractional (UnderlyingReal o)) => MemberLens o Momentum
- kineticEnergy :: (UseReal o, Fractional (UnderlyingReal o)) => MemberLens o KineticEnergy
- fromMassVelocity :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => real -> Vec real -> o
- fromMassMomentum :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => real -> Vec real -> o
- laserBeam :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => o
- duck :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => o
- lens :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => o
- banana :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => o
- envelope :: (Objective o, UseReal o, UseString o, Fractional (UnderlyingReal o), IsString (UnderlyingString o)) => o
- ghost :: Objective o => o

# Documentation

First, let us create a tiny two-dimensional vector class.
We make it an instance of `Arbitrary`

to use them later for tests.

Vec a a |

Now, let us introduce the concepts of `Mass`

, `Velocity`

,
`Momentum`

and `KineticEnergy`

. Any such concepts are described
in terms of `Member`

labels.

To define a member with compound types like vector of real numbers,
we use `UnderlyingReal`

to
ask the object which real value it prefers, then put the response
into the type constructors.

We also give a fallback accessor here. If the `velocity`

field is missing, we attempt to re-calculate it
from the `mass`

and `momentum`

. Here is how we can do that.

data KineticEnergy Source

`kineticEnergy`

, unless given explicitly, is defined in terms of `mass`

and `velocity`

.

Typeable KineticEnergy | |

(Typeable KineticEnergy, Typeable (ValType o KineticEnergy), Objective o, UseReal o, Fractional (UnderlyingReal o)) => Member o KineticEnergy |

mass :: MemberLens o MassSource

Now we define the lenses.

momentum :: (UseReal o, Fractional (UnderlyingReal o)) => MemberLens o MomentumSource

kineticEnergy :: (UseReal o, Fractional (UnderlyingReal o)) => MemberLens o KineticEnergySource

fromMassVelocity :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => real -> Vec real -> oSource

We can write functions that would construct a point particle from its mass and velocity. And we can make the function polymorphic over the representation of the real numbers the objects prefer.

fromMassMomentum :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => real -> Vec real -> oSource

We can also construct a point particle from its mass and momentum.

laserBeam :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => oSource

We define an instance of point-like particle. And again, we can keep it polymorphic, so that anyone can choose its concrete type later, according to their purpose. Thus we will achieve the polymorphic encoding of the knowledge of this world, in Haskell.

`>>>`

Just 1631.25`(laserBeam :: Object DIT) ^? kineticEnergy`

`>>>`

Just (6525 % 4)`(laserBeam :: Object Precise) ^? kineticEnergy`

Moreover, we can ask Ichiro to sign the ball. Usually, we needed to create a new data-type to add a new field. But with 'dynamic-object' we can do so without changing the type of the ball. So, we can put our precious, one-of-a-kind ball into toybox together with less uncommon balls, and with various other toys. And still, we can safely access the contents of the toybox without runtime errors, and e.g. see which toy is the heaviest.

`>>>`

`let (mySpecialBall :: Object DIT) = laserBeam & insert Autograph "Ichiro Suzuki"`

`>>>`

`let toybox = [laserBeam, mySpecialBall]`

`>>>`

`let toybox2 = toybox ++ [duck, lens, banana, envelope, ghost]`

`>>>`

5.2`maximum $ mapMaybe (^?mass) toybox2`

duck :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => oSource

lens :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => oSource

banana :: (Objective o, UseReal o, Fractional real, real ~ UnderlyingReal o) => oSource

envelope :: (Objective o, UseReal o, UseString o, Fractional (UnderlyingReal o), IsString (UnderlyingString o)) => oSource