## Method Chaining

A Fluent Interface is a chain of object-modifications that return the modified object on each chained modification.

```
import Prelude hiding ((.))
x.f = f x
data Shape = Circle { radius :: Float } deriving (Show)
doubleShapeArea(Circle r) = Circle(r * sqrt(2))
area(Circle r) = r^2 * pi
circ = Circle(2)
main = do {
print(circ);
print(circ.doubleShapeArea);
print(circ.doubleShapeArea.doubleShapeArea);
print(circ.area);
print(circ.doubleShapeArea.area);
print(circ.doubleShapeArea.doubleShapeArea.area);
}
```

As we can see, `doubleShapeArea`

can be chained as often as we want because it returns a (modified) `Shape`

object.

## Private Constructors, Private Accessors

In order to **enforce** our Fluent Interface, we make the constructor `Circle`

and the "deconstructor" `radius`

private. Otherwise anyone who imports our module could write their own `doubleShapeArea`

.

```
-- Geometry.hs
module Geometry (Shape, doubleShapeArea, circ) where
data Shape = Circle { radius :: Float }
circ = Circle(2)
doubleShapeArea(Circle r) = Circle(r * sqrt(2))
-- Main.hs
module Main where
import Geometry -- without Circle, but with circ
main = do {
print(circ);
print(circ.doubleShapeArea);
}
```

In the export list of our module `Geometry`

we have included only `Shape`

but not `Circle`

and `radius`

, thereby making `Shape`

public, leaving `Circle`

and `radius`

private. A user of `Geometry`

now relies on imported `Circle`

objects like `circ`

and methods like `doubleShapeArea`

. In other words, we have successfully enforced our Fluent Interface, but our module has become very inflexible, as it doesn't allow for constructing `Circle`

objects.

## Factories

We can easily implement and export a factory method `makeCircle`

which constructs a `Circle`

object but since it's technically not a constructor, it can't be used in pattern matching in order to access `radius`

. In return we get a more flexible module with a Fluent Interface that is still enforced.

```
-- Geometry.hs
module Geometry (Shape, doubleShapeArea, makeCircle) where
data Shape = Circle { radius :: Float }
makeCircle = Circle
doubleShapeArea(Circle r) = Circle(r * sqrt(2))
-- Main.hs
module Main where
import Geometry -- without Circle, but with makeCircle
circ = makeCircle(2)
main = do {
print(circ);
print(circ.doubleShapeArea);
}
```

## A Fluent Interface

With the Factory Pattern in place, we have implemented a Fluent Interface. Let's write an interface (FP lingo: *type class*) for Fluent Interfaces. Apparently, all we need is a factory method like `makeCircle`

that returns an object. Let's call it `make`

then.

```
import Prelude hiding ((.))
x.f = f x
doubleShapeArea(Circle(r)) = Circle(r * sqrt(2))
-- show
class Fluent object where
make :: Float -> object
instance Fluent Shape where
make = Circle
data Shape = Circle { radius :: Float } deriving (Show)
circ = make(2) :: Shape
main = do {
print(circ.doubleShapeArea);
}
-- /show
```

## Polymorphism

As we can see, this `Fluent`

interface requires an implementation of a `make`

method that takes a `Float`

as an argument. We can get to a more generic solution with an additional type variable `a`

instead of `Float`

. (`object`

is a type variable as well.) By doing so, we make `Shape`

*polymorphic*, (Now we can instantiate `Circle`

objects that have a `Double`

precision `radius`

.)

```
import Prelude hiding ((.))
x.f = f x
doubleShapeArea(Circle(r)) = Circle(r * sqrt(2))
-- show
class Fluent object where
make :: a -> object(a)
instance Fluent Shape where
make = Circle
data Shape a = Circle { radius :: a } deriving (Show)
circ = make(2) :: Shape(Double)
main = do {
print(circ.doubleShapeArea);
}
-- /show
```

In the next tutorial we shall add even more flexibility to Fluent Interfaces by making them *programmable*.