-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Object-oriented programming with duck typing and singleton classes. -- -- This package aims to combine the merit of Haskell's open, strong type -- system with flexible Object-oriented programming found in -- dynamically-typed languages such as python or ruby. -- -- Objects are implemented as Maps from method keys to -- values. Each key specifies its own value types. You can add new -- members at runtime, for any instances of the object (singleton class). -- At the same time, you have typed and runtime-error-free access to the -- members (duck typing). -- -- See Data.Object.Dynamic.Examples.PointParticle for examples. @package dynamic-object @version 0.2 module Data.Object.Dynamic.Types -- | The Object type, where u carrying the information of -- its underlying types. newtype Object u Object :: Table -> Object u unObject :: Object u -> Table -- | The Table within an Object that carries all the member -- data. newtype Table Table :: Map TypeRep Dynamic -> Table unTable :: Table -> Map TypeRep Dynamic -- | o is an Objective if given its type information, there -- is an equivalence between o and the Table. class Objective o where tableMap = table . (iso unTable Table) table :: Objective o => Simple Iso o Table tableMap :: Objective o => Simple Iso o (Map TypeRep Dynamic) -- | This means that memb is one of the member labels of -- o. The ValType of the member depends both on the label -- and (the underlying types of) the object. class (Objective o, Typeable memb, Typeable (ValType o memb)) => Member o memb where type family ValType o memb :: * -- | The lens for accessing the Member of the Object. type MemberLens o memb = Member o memb => Simple Traversal o (ValType o memb) -- | A utility function for creating a MemberLens . memberLensDef :: Member o memb => memb -> (o -> Maybe (ValType o memb)) -> MemberLens o memb -- | create a MemberLens without any default values. memberLens :: Member o memb => memb -> MemberLens o memb -- | Given a pair of Member label and a value, create the data field -- for the member and inserts the value. insert :: (Objective o, Member o memb, ValType o memb ~ val, Typeable memb, Typeable val) => memb -> val -> o -> o instance Objective (Object u) module Data.Object.Dynamic.Underlying -- | The declaration of instance Objective obj , -- instance UseReal obj means that the -- obj is an Object and is ready to tell the -- Members which type to use to represent the real numbers. class Typeable (UnderlyingReal a) => UseReal a where type family UnderlyingReal a :: * -- | Underlying integer types. class Typeable (UnderlyingInteger a) => UseInteger a where type family UnderlyingInteger a :: * -- | Underlying string types. class Typeable (UnderlyingString a) => UseString a where type family UnderlyingString a :: * instance UseString u => UseString (Object u) instance UseInteger u => UseInteger (Object u) instance UseReal u => UseReal (Object u) -- | This module provides two presets for the Object: DIT -- for daily use, and Precise for arbitrary precision -- calculations. module Data.Object.Dynamic.Presets -- | Object DIT uses Double for real numbers, -- Int for integers and Text for strings. -- --
-- >>> typechecks :: (UnderlyingReal (Object DIT) ~ Double) => Bool -- True -- -- >>> typechecks :: (UnderlyingInteger (Object DIT) ~ Int) => Bool -- True -- -- >>> typechecks :: (UnderlyingString (Object DIT) ~ Data.Text.Text) => Bool -- True --data DIT -- | Object Precise uses Double for real numbers, -- Int for integers and Text for strings. -- --
-- >>> typechecks :: (UnderlyingReal (Object Precise) ~ Rational) => Bool -- True -- -- >>> typechecks :: (UnderlyingInteger (Object Precise) ~ Integer) => Bool -- True -- -- >>> typechecks :: (UnderlyingString (Object Precise) ~ Data.Text.Text) => Bool -- True --data Precise instance UseString Precise instance UseInteger Precise instance UseReal Precise instance UseString DIT instance UseInteger DIT instance UseReal DIT -- | This module re-exports things needed to use Objects, and adds a -- few utility functions. module Data.Object.Dynamic -- | The Object type, where u carrying the information of -- its underlying types. data Object u -- | An empty object. empty :: Objective o => o -- | Given a pair of Member label and a value, create the data field -- for the member and inserts the value. insert :: (Objective o, Member o memb, ValType o memb ~ val, Typeable memb, Typeable val) => memb -> val -> o -> o -- | The lens for accessing the Member of the Object. type MemberLens o memb = Member o memb => Simple Traversal o (ValType o memb) -- | 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. module Data.Object.Dynamic.Examples.PointParticle -- | First, let us create a tiny two-dimensional vector class. We make it -- an instance of Arbitrary to use them later for tests. data Vec a Vec :: a -> a -> Vec a -- | Now, let us introduce the concepts of Mass, Velocity, -- Momentum and KineticEnergy. Any such concepts are -- described in terms of Member labels. data Mass Mass :: Mass -- | 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. data Velocity Velocity :: Velocity data Momentum Momentum :: Momentum data KineticEnergy KineticEnergy :: KineticEnergy -- | Now we define the accessors. Accessors for Members without -- default methods are straightforward. mass :: MemberLens o Mass -- | If the velocity field is missing, we attempt to re-calculate it -- from the mass and momentum. Here is how we can do that. velocity :: (UseReal o, Fractional (UnderlyingReal o)) => MemberLens o Velocity -- | If the momentum field is missing, we re-calculate it from the -- mass and velocity. momentum :: (UseReal o, Fractional (UnderlyingReal o)) => MemberLens o Momentum -- | kineticEnergy is defined in terms of mass and -- velocity . kineticEnergy :: (UseReal o, Fractional (UnderlyingReal o)) => MemberLens o KineticEnergy -- | 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. fromMassVelocity :: (Objective o, UseReal o, Fractional real, real ~ (UnderlyingReal o)) => real -> Vec real -> o -- | We can also construct a point particle from its mass and momentum. fromMassMomentum :: (Objective o, UseReal o, Fractional real, real ~ (UnderlyingReal o)) => real -> Vec real -> o -- | 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. -- --
-- >>> (laserBeam :: Object DIT) ^? kineticEnergy -- Just 1631.25 -- -- >>> (laserBeam :: Object Precise) ^? kineticEnergy -- Just (6525 % 4) ---- -- 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] -- -- >>> maximum $ mapMaybe (^?mass) toybox2 -- 5.2 --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 instance Typeable1 Vec instance Typeable Mass instance Typeable Velocity instance Typeable Momentum instance Typeable KineticEnergy instance Typeable Autograph instance Eq a => Eq (Vec a) instance Show a => Show (Vec a) instance Ord a => Ord (Vec a) instance (Objective o, UseString o) => Member o Autograph instance (Objective o, UseReal o) => Member o KineticEnergy instance (Objective o, UseReal o) => Member o Momentum instance (Objective o, UseReal o) => Member o Velocity instance (Objective o, UseReal o) => Member o Mass instance Arbitrary a => Arbitrary (Vec a)