# [Haskell-cafe] Abstraction in data types

Alexander Solla ajs at 2piix.com
Thu Mar 18 02:36:37 EDT 2010

```On Mar 17, 2010, at 10:27 PM, Darrin Chandler wrote:

Let's go back to your original code:

data Point	= Cartesian (Cartesian_coord, Cartesian_coord)
| Spherical (Latitude, Longitude)

type Center = Point

data Shape	= Circle Center Radius
| Polygon [Point]

normalize_shape :: Shape -> Shape
normalize_shape Circle c r = Circle c r
normalize_shape Polygon ps = Polygon \$ fmap normalize_point ps where
normalize_point = something appropriate for the function.

In fact, you could lift this into a higher order function, that takes
a normalize_point function as an argument:

normalize_shape :: (Point -> Point) -> Shape -> Shape
normalize_shape f (Circle c r)= Circle (f c) r
normalize_shape f (Polygon ps) = Polygon \$ fmap f ps

Now, I'm not suggesting that you should always normalize shapes, as I
had with normalize_point before.  But this combinator captures some
nice, generic logic. For example, you can do stuff like:

cartesian_shape :: Shape -> Shape
cartesian_shape = normalize_shape cartesian_point where ...

normalize_shape is the sort of function you would use while defining a
function, and possibly provide function specific behavior in the
function's where clause.

double_shape :: Shape -> Shape
double_shape (Circle c r) = Circle c (2 * r)
double_shape (Polygon ps) = Polygon \$ normalize_shape (double_point .
cartesian_point) ps where
double_point Cartesian (x, y) = Cartesian (sqrt(2) * x, sqrt(2) * y)
```