A C++ programmer trying to learn Haskell here. Please excuse this probably easy question. I want to translate a program that represents 3D shapes. In C++ I have something like:
class Shape { public: std::string name; Vector3d position; }; class Sphere : public Shape { public: float radius; }; class Prism : public Shape { public: float width, height, depth; };
I am trying to translate this to Haskell (using records?) so that I can have some functions which know how to operate on a Shape (like accessing its name and position), and others than know only how to operate on spheres, like calculating something based on its position and radius.
In C++ a member function could just access these parameters but I'm having a hard time figuring out how to do this in Haskell with records, or type classes, or whatever.
Thanks.
The straight-forward translation.
type Vector3D = (Double, Double, Double) class Shape shape where name :: shape -> String position :: shape -> Vector3D data Sphere = Sphere { sphereName :: String, spherePosition :: Vector3D, sphereRadius :: Double } data Prism = Prism { prismName :: String, prismPosition :: Vector3D, prismDimensions :: Vector3D } instance Shape Sphere where name = sphereName position = spherePosition instance Shape Prism where name = prismName position = prismPosition
You usually wouldn't do this, though; it's repetitious and polymorphic lists require language extensions.
Instead, sticking them into a single closed datatype is probably the first solution you should go for.
type Vector3D = (Double, Double, Double) data Shape = Sphere { name :: String, position :: Vector3D, radius :: Double } | Prism { name :: String, position :: Vector3D, dimensions :: Vector3D }
You can certainly simulate multiple levels of inheritance by creating more typeclasses:
class (Shape shape) => Prism shape where dimensions :: Vector3D data RectangularPrism = ... data TriangularPrism = ... instance Prism RectangularPrism where ... instance Prism TriangularPrism where ...
You can also simulate it by embedding datatypes.
type Vector3D = (Double, Double, Double) data Shape = Shape { name :: String, position :: Vector3D } data Sphere = Sphere { sphereToShape :: Shape, radius :: Double } newSphere :: Vector3D -> Double -> Shape newSphere = Sphere . Shape "Sphere" data Prism = Prism { prismToShape :: Shape, dimensions :: Vector3D } data RectangularPrism = RectangularPrism { rectangularPrismToPrism :: Prism } newRectangularPrism :: Vector3D -> Vector3D -> RectangularPrism newRectangularPrism = (.) RectangularPrism . Prism . Shape "RectangularPrism" data TriangularPrism = TriangularPrism { triangularPrismToPrism :: Prism } newTriangularPrism :: Vector3D -> Vector3D -> TriangularPrism newTriangularPrism = (.) TriangularPrism . Prism . Shape "TriangularPrism"
But simulating OO in Haskell is not anywhere near as satisfying as actually thinking in a Haskellish way. What are you trying to do?
(Also note that all of these solutions only permit upcasts, downcasting is unsafe and disallowed.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With