In FP, contracts don't lie

Let's look an example of some imperative code:

type Dividend struct {
Val int
}
func (n Dividend) Divide(pisor int) int {
return n.Val/pisor
}

func main() {
d := Dividend{2}
fmt.Printf("%d", d.Divide(0))
}

What is our contract in the preceding code?

The contract is our method's signature: func (n Dividend) Divide(pisor int) int

What three questions must our contract answer?

  1. What does our contract expect? 
  • Answer: It expects the following: 
    • The Dividend.Val to be populated with an int
    • The pisor to be an int
  1. What does our contract guarantee? 
  • Answer: It promises to return an integer
  1. What does the contract maintain? 
  • Answer: Not applicable in this simple case

What happens when we run the preceding code?

We get a runtime panic! Did our contract hold true, or did it lie to us?

In pure FP, we don't rely on lowly types like int, char, or even string. We leverage the full power of an amazing type class system.

In a pure FP language like Haskell, we can define a PostiveInt type. So, instead of writing a method to validated that an input parameter is positive, we define a type named PostiveInt that guarantees that only positive integers will be input:

PositiveInt :: Int -> Maybe Positive
PositiveInt n = if (n < 0) then Nothing else Just (Positive n)

In FP terms, LSP says, Contracts don't lie;

In FP, we don't have to rely on our test suite to verify that our application properly enforces it requirements. In FP, assuming we have designed our software properly, if it compiles then it is correct. We let our type system enforce our requirements.

In an OOP courting relationship, the input (candidate spouse) is only verified to be Female. When we later discover that she is not the right type of woman, that is, she's already married, that would render the marriage contract invalid.

This is what happens when we don't properly type check our input:

This is the picture when we use pure FP:

Looks simple, but where are the external interactions like in-laws that can lead to porce? What about children? Aren't they what we might call side-effects of a marriage?

Monads provide a way for our couple to interact with the external world; To handle possibly harmful influences and generate beautiful side effects. It looks something like this:

The trick to Monads is that all external interactions are contained (in the box). We'll cover Monads in depth in our last chapter.

This book is about learning functional programming in Go. Hence, we will embrace the full meaning of the term functional. Functional does not only mean pure. If we're using functions, we're doing functional programming. Go is a multi-paradigm language that does not force us to be completely pure or completely imperative. The vast majority of Go code these days is imperative... take the standard libraries as an example. There is a time and a place for implementing pure functional programming techniques. The more we learn about all aspects of Go's functional capabilities, and pure functional programming concepts, the better equipped we will be to prudently apply the proper style of coding to meet our application development requirements.

Let's see the LSP at work with a duck typing example.