﻿ F# Topics: Composing Functions F# Topics: Composing Functions

 Introduction
 Imagine you have two or more functions in a program: the functions take the same number and type(s) of argument(s); the assignment(s) performed by one (or more) of the function(s) can be used by another function. For example, consider the area of a circle. It is calculated as Radius2 * PI (which is approximately 3.14156...). The area of a sphere is gotten by simply multiplying the area of a circle by 4 (4 * Radius2 * PI). If you already have a function that calculates the area of a circle, you can simply "add" it to another simpler function to get the area of a sphere.

You can "add" one function to another. This is referred to as composing the functions. First, you must define the functions. Here are examples:

```let PI = 3.14156

let multiplyBy4 value = 4.00 * value // Area of a Sphere```

To compose two functions, you use the >> or the << operator. As mentioned in the beginning, composed functions use the same number and type(s) of argument(s). To get the result of composing the functions, you must provide the argument(s) to the composition. You have various options. If you want to immediately use the result of the composition, you can include the operation in parentheses followed by the argument(s). Here is an example:

```open System
open System.Windows.Forms

// Form: Geometry - Sphere
let sphere : Form = new Form()
sphere.Width  <- 285
sphere.Height <- 170
sphere.Text <- "Geometry - Sphere"

let lblRadius : Label = new Label()

let txtRadius : TextBox = new TextBox()

// Button: Calculate
let btnCalculate : Button = new Button()
btnCalculate.Left <- 186
btnCalculate.Top  <-  16
btnCalculate.Text <- "Calculate"

// Label: Diameter
let lblDiameter : Label = new Label()
lblDiameter.Left  <- 22
lblDiameter.Top   <- 53
lblDiameter.Width <- 80
lblDiameter.Text  <- "Diameter:"

// Text Box: Diameter
let txtDiameter : TextBox = new TextBox()
txtDiameter.Left  <- 105
txtDiameter.Top   <- 50
txtDiameter.Width <- 74

// Label: Surface Area
let lblSurfaceArea : Label = new Label()
lblSurfaceArea.Left  <- 22
lblSurfaceArea.Top   <- 82
lblSurfaceArea.Width <- 80
lblSurfaceArea.Text  <- "Surface Area:"

// Text Box: Surface Area
let txtSurfaceArea : TextBox = new TextBox()
txtSurfaceArea.Left  <- 105
txtSurfaceArea.Top   <- 80
txtSurfaceArea.Width <- 74

// Label: Volume
let lblVolume : Label = new Label()
lblVolume.Left  <-  22
lblVolume.Top   <- 110
lblVolume.Width <-  80
lblVolume.Text  <- "Volume:"

// Text Box: Volume
let txtVolume : TextBox = new TextBox()
txtVolume.Left  <- 105
txtVolume.Top   <- 110
txtVolume.Width <-  74

// Button: Close
let btnClose : Button = new Button()
btnClose.Left  <- 186
btnClose.Top   <- 108
btnClose.Text <- "Close"

let btnCloseClick _ = sphere.Close()

let PI = 3.14156

let multiplyBy4 value = 4.00 * value // Area of a Sphere

let btnCalculateClick e =
let diameter   = calculateCircleDiameter <| radius
let circleArea = calculateCircleArea <| radius
let sphereArea = (calculateCircleArea << multiplyBy4) radius
let volume     = multiplyBy4 <| radius

let strDiameter = sprintf "%f" diameter
let strSphereArea = sprintf "%f" sphereArea
let strVolume   = sprintf "%f" volume

txtDiameter.Text    <- strDiameter
txtSurfaceArea.Text <- strSphereArea
txtVolume.Text      <- strVolume

Application.Run sphere```

Here is an example of running the program:  Another option is to assign the composition without the argument(s) to a function value. Here is an example:

`let area = calculateCircleArea << multiplyBy4`

Then, to use the result of the composition, call the function and pass the desired value(s). Here is an example:

```let PI = 3.14156
let multiplyBy4 value = 4.00 * value // Area of a Sphere

let btnCalculateClick e =
let diameter   = calculateCircleDiameter <| radius
let circleArea = calculateCircleArea <| radius
let sphereArea = calculateCircleArea << multiplyBy4
let volume     = multiplyBy4 <| radius

let strDiameter = sprintf "%f" diameter
let strSphereArea = sprintf "%f" (sphereArea radius)
let strVolume   = sprintf "%f" volume

txtDiameter.Text    <- strDiameter
txtSurfaceArea.Text <- strSphereArea
txtVolume.Text      <- strVolume```

As mentioned already, when composing two functions, you place one function to the left of << or >> and one function to the right of << or >>:

• If you use the << operator, the function on the left side would execute first. Here is an example:
```let PI = 3.14156;

let multiplyBy4 value = 4.00 * value; // Area of a Sphere

let area = calculateCircleArea << multiplyBy4
let result = area 25.85```
• If you use the >> operator, the function on the right side would execute first. Here is an example:
```let greetings msg = msg + " - F# is fun!"
let define    msg = "Announcement: " + msg
let combine = define >> greetings

let g = combine "Welcome to the wonderful world of functional programming"

sprintf "%s" g```

 Composing Many Functions

In the same way, you can compose as many functions as you want. Here is an example with three functions:

```open System
open System.Windows.Forms

let exercise : Form = new Form()
exercise.Width <- 235
exercise.Height <- 108
exercise.Text <- "Salary Evaluation"

let lblHourlySalary : Label = new Label()
lblHourlySalary.Left <- 12
lblHourlySalary.Top <- 22
lblHourlySalary.Width <- 82
lblHourlySalary.Text <- "Hourly Salary:"

let txtHourlySalary : TextBox = new TextBox()
txtHourlySalary.Left <- 95
txtHourlySalary.Top <- 18
txtHourlySalary.Width <- 40
txtHourlySalary.Text <- "0"

let lblYearlySalary : Label = new Label()
lblYearlySalary.Left <- 12
lblYearlySalary.Top <- 45
lblYearlySalary.Width <- 82
lblYearlySalary.Text <- "Yearly Salary:"

let txtYearlySalary : TextBox = new TextBox()
txtYearlySalary.Left <- 95
txtYearlySalary.Top <- 45
txtYearlySalary.Width <- 110
txtYearlySalary.Text <- "0"

let btnCalculate : Button = new Button()
btnCalculate.Left <- 140
btnCalculate.Top <- 16
btnCalculate.Width <- 65
btnCalculate.Text <- "Calculate"

let btnCalculateClick e =
let hourlySalary = float txtHourlySalary.Text

let EvaluateDailySalary salary = salary * 8.00  // Daily Salary   = Hourly Salary * 8
let multiplBy20 value = value * 20.00           // Monthly Salary = Daily Salary * 20
let multiplBy12 value = value * 12.00           // Yearly Salary  = Monthly Salary * 12

let yearEvaluation = EvaluateDailySalary >> multiplBy20 >> multiplBy12
let yearlySalary = yearEvaluation hourlySalary

txtYearlySalary.Text <- string yearlySalary

Application.Run exercise```

Here is an example of executing the program:  Here is an example with five functions:

```let btnCalculateClick e =
let hourlySalary = float txtHourlySalary.Text

// Daily Salary   = Hourly Salary * 8
let EvaluateDailySalary salary = salary * 8.00
// Weekly Salary = Daily Salary * 5
let multiplBy5 value = value * 5.00
// Bi-Monthly Salary = Weekly Salary * 2
// Monthly Salary = Bi-Monthly Salary * 2
let multiplBy2 value = value * 2.00
// Yearly Salary  = Monthly Salary * 12
let multiplBy12 value = value * 12.00

let yearEvaluation = EvaluateDailySalary >> multiplBy5 >> multiplBy2 >> multiplBy2 >> multiplBy12
let yearlySalary = yearEvaluation hourlySalary

txtYearlySalary.Text <- string yearlySalary```

When composing many functions, to make your code easy to ready, you can put them on different lines with appropriate indentation. Here is an example:

```let btnCalculateClick e =
let hourlySalary = float txtHourlySalary.Text

// Daily Salary   = Hourly Salary * 8
let EvaluateDailySalary salary = salary * 8.00
// Weekly Salary = Daily Salary * 5
let multiplBy5 value = value * 5.00
// Bi-Monthly Salary = Weekly Salary * 2
// Monthly Salary = Bi-Monthly Salary * 2
let multiplBy2 value = value * 2.00
// Yearly Salary  = Monthly Salary * 12
let multiplBy12 value = value * 12.00

let yearEvaluation = EvaluateDailySalary
>> multiplBy5
>> multiplBy2
>> multiplBy2
>> multiplBy12
let yearlySalary = yearEvaluation hourlySalary

txtYearlySalary.Text <- string yearlySalary```