views:

121

answers:

0

I've been using F# recently and tried to code in a functional way rather than doing OOP all over again in a different syntax. I've now run into a problem that I could solve with a mix of inheritance and discriminated unions but for which I'm trying to find a pure functional style representation.

What I want to model is something like this (changed to preserve the pattern since I can't use the actual code):

type Shape =
    | Rectangle of Size * Size
    | Circle of Diameter

so far so good, but now I need to represent a collection of additional properties relevant for the different types of shapes, like:

type ShapeProperty =
    | Color of Shape * Color // Fine, valid for all shapes
    | Rotation of Shape * Angle // Wants to be Rotation of Rectangle * Angle
    | Details of Shape * int // Wants to be Detail of Circle * int

If instead of using a discriminated union for Shape, I'd used a base class and inheritance, I could refer to the actual types and make sure Rotation could only be applied to Rectangle and not Circle, but now I can't. Is there a way of implementing something like that while still keeping to pure functional data structures?

Edit:

My current solution is to separate the definition of a individual shapes from the fact that shapes are at all related, like this:

type Rectangle = Rectangle of Size * Size // Or using a record type
type Circle = Circle of Diameter // Or using a record type
type Shape = RectangleShape of Rectangle | CircleShape of Circle

which means that I then have type to refer to in ShapeProperty:

type ShapeProperty =
    | Color of Shape * Color
    | Rotation of Rectangle * Angle
    | Details of Circle * int

This feels a bit clumsy as now need to encapsulate each shape in the Shape type to store them in a collection, but it does give me a way of expressing the type safety I'm after. Any improvements on this would be welcome.