Haskell evaluates data type properties only once at first access?

In mandatory / object-oriented stateful programming, it would be very common and useful to declare a structure such as the following:

struct RigidBody {
  float m_mass;
  float m_inverseMass;
  Mat3 m_localInverseInertiaTensor;
  Mat3 m_globalInverseInertiaTensor;

  Vec3 m_globalCentroid;
  Vec3 m_localCentroid;

  Vec3 m_position;
  Mat3 m_orientation;
  Vec3 m_linearVelocity;
  Vec3 m_angularVelocity;
};

Source: http://allenchou.net/2013/12/game-physics-motion-dynamics-implementations/

There are many properties that can be calculated directly from others, for example m_inverseMassfrom m_mass. In a stateless programming language such as Haskell, getting derived values ​​is simple enough:

data RigidBody = RigidBody {mass :: Float}

inverseMass :: RigidBody -> Float
inverseMass body = 1 / mass body

inverseMass , , , , , . memoization, , , . ?

+4
2

@4castle @Shersh , :

data RigidBody = RigidBody
  { m_mass :: Float
  , m_inverseMass :: Float }

RigidBody s:

rigidBody mass = RigidBody mass (1/mass)

1/mass thunk m_inverseMass, , memoization.

, global* local*, . :

module Rigid where

type Vec3 = Double  -- just to type check

data RigidBody = RigidBody
  { m_mass :: Float
  , m_inverseMass :: Float
  , m_pos :: Vec3
  , m_localCentroid :: Vec3
  , m_globalCentroid :: Vec3
  }

rigidBody mass pos centroid =
  RigidBody mass (1/mass) pos centroid (centroid + pos)

move body delta =
  rigidBody (m_mass body)
            (m_pos body + delta)
            (m_localCentroid body)

, , , , .

+11

inverseMass Maybe Float RigidBody. inverseMass - Just someMass, . Nothing, RigidBody. . , , Haskell .

, RigidBody , :

data RigidBody = RigidBody 
    { rigidBodyMass        :: Float
    , rigidBodyInverseMass :: Maybe Float }

inverseMass :: RigidBody -> (Float, RigidBody)
inverseMass b@(RigidBody _ (Just inv)) = (inv, b)
inverseMass   (RigidBody mass Nothing) = let inv = 1 / mass 
                                         in (inv, RigidBody mass (Just inv))

, . , . , , State . State RigidBody , , . :

inverseMass :: State RigidBody Float
inverseMass = do
    RigitBody inv maybeInverse <- get
    case maybeInverse of
        Just inv -> pure inv
        Nothing  -> do
            let inv = 1 / mass
            put $ RigidBody mass (Just inv)
            pure inv

inverseMass , , .

, , ++, . RigidBody. , RigidBody, . , , RigidBody. Haskell ( ) , . , . inverseMass monadic action ( , ) . Haskell .

, : , . Haskell , , .

0

Source: https://habr.com/ru/post/1686698/


All Articles