# The shape design problem

**URL:** <https://discuss.ocaml.org/t/the-shape-design-problem/7810>\
**Category:** Community\
**Created:** [May 8, 2021, 5:23pm UTC](https://discuss.ocaml.org/t/the-shape-design-problem/7810 "2021-05-08T17:23:22Z")\
**Posts on this page:** 1\
**Showing post:** 8

<div class="post-metadata">

**Author:** ![kantian](https://avatars.discourse-cdn.com/v4/letter/k/4bbf92/32.png) [@kantian](https://discuss.ocaml.org/u/kantian)\
**Post date:** [May 9, 2021, 9:11am UTC](https://discuss.ocaml.org/t/the-shape-design-problem/7810/8 "2021-05-09T09:11:19Z")

</div>

Interesting problem not difficult to solve in OCaml. For sure, you could use the object system but I do not like it a lot, and it’s not really fun. To have more fun, and since it’s an expression problem, lets use the full expressiveness power of the OCaml type system : modules, first-class modules and GADT. 🙂

First define your algebra on shapes as a module type:

```ocaml
module type SHAPE = sig
  type t
  val area : t -> float
  val draw : t -> unit
end

```

then implement your different kinds of shapes:

```ocaml
module Point : SHAPE = struct
  type t = {x : int; y : int}
  let area _ = 0.0
  let draw {x; y} = ...
end

module Circle : SHAPE = struct ... end
module Rectangle : SHAPE = struct ... end

```

Now, since you want containers for shapes (to iterate over them), you need to define the type of shapes, and that’s where we use GADT. According to your definition, a shape is something with an area that we can draw. Here’s how we define this in OCaml:

```ocaml
type shape = Shape : (module SHAPE with type t = 'a) * 'a -> shape

```

and now you can define, for instance, a list of shape:

```ocaml
let l = [Shape ((module Point), p1); Shape ((module Circle), c1); ...]

(* and iterate over it *)
List.iter (fun (Shape ((module M), v)) -> M.draw v) l

```

Basically a `shape` (as defined with a GADT) is similar to an object, for instance with a point:

```ocaml
let point x y = object
  val x = x
  val y = y
  method area = 0.0
  method draw () = ()
end

```

but here the instance variable (`x` and `y`) are really what define a point, and this type cannot be projected out of this object in the type system (that’s one of the reason I don’t like a lot the object sytem). And this object is just a flatten representation of the `shape` type

For a more detail use of this method [see this thread](https://discuss.ocaml.org/t/generalize-the-fields-of-a-record-to-apply-validation-other-ops/2785/5).

---

_[View the full topic](https://discuss.ocaml.org/t/the-shape-design-problem/7810)._
