## Method Cascades

In the last tutorial we saw how Programmable Fluent Interfaces can be implemented and that they are referred to as *Monads* in FP lingo. We will now start to use Haskell's built-in `Monad`

type class instead of our own `Fluent`

interface...

```
import Prelude hiding ((.))
x.f = f x
data Shape a = Circle { radius :: a } deriving (Show)
instance Monad Shape where
object >>= remake = remake(object.radius)
return = Circle
```

...but we will keep on using our own method synonyms `bind`

and `make`

.

```
bind = flip(>>=)
make = return
```

Everything should be working as before.

```
import Control.Monad
import Control.Applicative
import Data.Functor
import Prelude hiding ((.))
x.f = f x
data Shape a = Circle { radius :: a } deriving (Show)
instance Functor Shape where { fmap = liftM }
instance Applicative Shape where { pure = return; (<*>) = ap }
instance Monad Shape where
object >>= remake = remake(object.radius)
return = Circle
bind = flip(>>=)
make = return
-- show
doubleShapeArea(r) = make(r * sqrt(2))
circ = make(2) :: Shape(Double)
main = do {
print(circ);
print(circ.bind(doubleShapeArea));
}
-- /show
```

Let's add a redundant `.bind(make)`

to the method chain (it trivially returns its argument) and wrap both `doubleShapeArea`

and `make`

in closures in order to reflect the values being passed through the method chain.

```
import Control.Monad
import Control.Applicative
import Data.Functor
import Prelude hiding ((.))
x.f = f x
data Shape a = Circle { radius :: a } deriving (Show)
instance Functor Shape where { fmap = liftM }
instance Applicative Shape where { pure = return; (<*>) = ap }
instance Monad Shape where
object >>= remake = remake(object.radius)
return = Circle
bind = flip(>>=)
make = return
area(Circle r) = r^2 * pi
doubleShapeArea(r) = make(r * sqrt(2))
circ = make(2) :: Shape(Double)
-- show
main = do {
print(circ.bind(doubleShapeArea).bind(make));
print(circ.bind(\(a) -> a.doubleShapeArea).bind(\(b) -> make(b)));
}
-- /show
```

As we can imagine, `a`

is bound to `circ.radius`

, i.e. `2.0`

, and `b`

is bound to `radius`

of a `Circle`

object with twice as much area as `circ`

, i.e. a radius of `2.8284271247461903`

. Both `a`

and `b`

exist only inside the closures `\(a) -> a.doubleShapeArea`

and `\(b) -> b.make`

.

But, if we chose to bind `\(b) -> b.make`

to `doubleShapeArea`

*inside* the closure `\(a) -> a.doubleShapeArea`

, `a`

remains available to `make`

and we can apply `make`

to `a`

instead of `b`

, thereby ignoring `doubleShapeArea`

's return value.

```
import Control.Monad
import Control.Applicative
import Data.Functor
import Prelude hiding ((.))
x.f = f x
data Shape a = Circle { radius :: a } deriving (Show)
instance Functor Shape where { fmap = liftM }
instance Applicative Shape where { pure = return; (<*>) = ap }
instance Monad Shape where
object >>= remake = remake(object.radius)
return = Circle
bind = flip(>>=)
make = return
area(Circle r) = r^2 * pi
doubleShapeArea(r) = make(r * sqrt(2))
circ = make(2) :: Shape(Double)
-- show
main = do {
print(circ.bind(\(a) -> a.doubleShapeArea.bind(\(b) -> make(b))));
print(circ.bind(\(a) -> a.doubleShapeArea.bind(\(b) -> make(a))));
}
-- /show
```

We can also make some computations with `a`

and `b`

like `sqrt(a^2 + b^2)`

, which yields the radius of a circle that combines the area of two circles with radius `a`

and `b`

.

```
import Control.Monad
import Control.Applicative
import Data.Functor
import Prelude hiding ((.))
x.f = f x
data Shape a = Circle { radius :: a } deriving (Show)
instance Functor Shape where { fmap = liftM }
instance Applicative Shape where { pure = return; (<*>) = ap }
instance Monad Shape where
object >>= remake = remake(object.radius)
return = Circle
bind = flip(>>=)
make = return
area(Circle r) = r^2 * pi
doubleShapeArea(r) = make(r * sqrt(2))
circ = make(2) :: Shape(Double)
-- show
main = do {
print(circ.bind(\(a) -> a.doubleShapeArea.bind(\(b) -> make(sqrt(a^2 + b^2)))));
}
-- /show
```

Let's indent our code to reflect the Method Cascade.

```
import Control.Monad
import Control.Applicative
import Data.Functor
import Prelude hiding ((.))
x.f = f x
data Shape a = Circle { radius :: a } deriving (Show)
instance Functor Shape where { fmap = liftM }
instance Applicative Shape where { pure = return; (<*>) = ap }
instance Monad Shape where
object >>= remake = remake(object.radius)
return = Circle
bind = flip(>>=)
make = return
area(Circle r) = r^2 * pi
doubleShapeArea(r) = make(r * sqrt(2))
circ = make(2) :: Shape(Double)
-- show
main = do {
print(
circ.bind(\(a) ->
a.doubleShapeArea.bind(\(b) ->
make(sqrt(a^2 + b^2))
)
)
);
}
-- /show
```

As we can see, with each `bind`

we add a new variable to the scope of the Method Cascade.

Side note: I say *variable* instead of *value* because values declared in Method Cascades can be redeclared in an inner closure, thereby *overwriting* a previously declared value of an outer closure. This happens in `circ.bind(\(a) -> a.doubleShapeArea.bind(\(a) -> make(a)))`

, where `a`

is been bound to the `radius`

of `circ`

and then to the `radius`

of the return value of `doubleShapeArea`

.

## do-Notation

Let's change our indentation step by step in order to reflect this pattern. First, we append the closing parenthesis of the Method Cascade to the innermost closure.

```
import Control.Monad
import Control.Applicative
import Data.Functor
import Prelude hiding ((.))
x.f = f x
data Shape a = Circle { radius :: a } deriving (Show)
instance Functor Shape where { fmap = liftM }
instance Applicative Shape where { pure = return; (<*>) = ap }
instance Monad Shape where
object >>= remake = remake(object.radius)
return = Circle
bind = flip(>>=)
make = return
area(Circle r) = r^2 * pi
doubleShapeArea(r) = make(r * sqrt(2))
circ = make(2) :: Shape(Double)
-- show
circ' =
circ.bind(\(a) ->
a.doubleShapeArea.bind(\(b) ->
make(sqrt(a^2 + b^2))))
main = do {
print(circ');
}
-- /show
```

Now we seperate the `.bind(\(...) ->`

snippets and align the Method Cascade.

```
import Control.Monad
import Control.Applicative
import Data.Functor
import Prelude hiding ((.))
x.f = f x
data Shape a = Circle { radius :: a } deriving (Show)
instance Functor Shape where { fmap = liftM }
instance Applicative Shape where { pure = return; (<*>) = ap }
instance Monad Shape where
object >>= remake = remake(object.radius)
return = Circle
bind = flip(>>=)
make = return
area(Circle r) = r^2 * pi
doubleShapeArea(r) = make(r * sqrt(2))
circ = make(2) :: Shape(Double)
-- show
circ' =
circ .bind(\(a) ->
a.doubleShapeArea .bind(\(b) ->
make(sqrt(a^2 + b^2))))
main = do {
print(circ');
}
-- /show
```

As we can see, Method Cascades that use a Programmable Fluent Interfaces introduce a variable to the scope of each chained method, in our case `a`

and `b`

, that are extracted from objects that implement the Fluent Interface. It's like writing `a <- circ`

and `b <- a.doubleShapeArea`

. Haskell uses this pattern extensively and therefore provides syntactic sugar called *do-notation* that allows for using this patterns exactly like that.

```
import Control.Monad
import Control.Applicative
import Data.Functor
import Prelude hiding ((.))
x.f = f x
data Shape a = Circle { radius :: a } deriving (Show)
instance Functor Shape where { fmap = liftM }
instance Applicative Shape where { pure = return; (<*>) = ap }
instance Monad Shape where
object >>= remake = remake(object.radius)
return = Circle
area(Circle r) = r^2 * pi
doubleShapeArea(r) = return(r * sqrt(2))
circ = return(2) :: Shape(Double)
-- show
circ' = do {
a <- circ;
b <- a.doubleShapeArea;
return(sqrt(a^2 + b^2));
}
main = do {
print(circ');
}
-- /show
```

The naming of Haskell's built-in `return`

(which we called `make`

) reflects that Method Cascades that use a Programmable Fluent Interface are powerful enough to model computations.