DEV Community 👩‍💻👨‍💻

Angelo
Angelo

Posted on

Maybe. Functional programming in Javascript with React.

Before I get into the main point of this article, which is to showcase the amazing Maybe monad. I would like cover a high level functional programming concept, composition. Composition is at the root of functional programming.

#Composition
const compose = f => g => x => f(g(x))
Enter fullscreen mode Exit fullscreen mode

Composition allows us to compose functions together.

// Add 10%
const addFederalTax = x => x * 1.1
// Add 15%
const addStateTax = x => x * 1.15

// Traditional
// const addTaxes = price => compose(addStateTax)(addFederalTax)(price)

// Point Free
const addTaxes = compose(addStateTax)(addFederalTax)

// Lets add State and Federal taxes to 5 Dollars
addTaxes(5.00) // 6.32
Enter fullscreen mode Exit fullscreen mode

Another cool concept being used above is point free style.

Great.

We will use the Maybe Monad in traversing some data, and then outputting safe to use data.

My love for McDonald's has inspired me to create a data set that represents a slice of some McDonald's restaurant's breakfast menu.

const restaurant = { 
    name: 'McDonalds',
    location: 'Kansas City',
    menu : {
    breakfast : [
            {name: 'Pancakes', options: ['Bacon', 'Sausage']},
            {name: 'McMuffin', options: ['Egg', 'Cheese', 'Sausage', 'Ham', 'Bacon']},
            {name: 'Coffee', sizes: ['Small', 'Medium', 'Large', 'X-Large'], options: ['Milk', 'Creme', 'Sugar']},
        ]
    }
}
Enter fullscreen mode Exit fullscreen mode

Maybes are great when working with data structures that are not reliable.
For example in our breakfast items example above, Coffee is the only option that includes sizes. Checking for sizes in Pancakes or Muffins would cause a runtime error. Not to mention that some locations may not even offer breakfast!

First, we want to make sure that breakfast is offered.

Before we get into the functional stuff.
Let's look at the imperative way, or more conventional style of checking if breakfast is offered.

function hasBreakfastMenu (restaurant){
    if(restaurant.menu && restaurant.menu.breakfast){
        return restaurant.menu.breakfast
    } else {
        // Do Something
        console.log('Not found')
    }
}

const breakfastMenuItems = hasBreakfastMenu(restaurant)
Enter fullscreen mode Exit fullscreen mode

Now, we will do the same in a functional style.

To achieve this we will use get from the Pratica library. The Pratica get function returns a Monad. Monads are safe, and protect against runtime errors.

// breakfastMenu.js
import { Maybe, get } from 'pratica'

const hasBreakfastMenu = get(['menu', 'breakfast'])

hasBreakfastMenu(restaurant).cata({
    Just: breakfastMenuItems => breakfastMenuItems,
    Nothing: () => console.log('Not found'),
})
Enter fullscreen mode Exit fullscreen mode

Great. Pretty simple? Right?

Check out the code below.

// breakfastMenu.js
import { Maybe, get } from 'pratica'

const hasBreakfastMenu = get(['menu', 'breakfast'])

/**
 *  hasSizes & hasOptions return us a Monad. 
 *  In this exampe we will see how Moands can be implemented in our UI.
 *  Using Monads will free us from using if / else statements in our UI Components.
 * */

const hasSizes = sizes => Maybe(sizes).chain(sizes => get(['sizes'])(sizes)) // Returns a Monad
const hasOptions = options => Maybe(options).chain(