---
category: tutorial
title: function
layout: post
---

The function monad augments standard JavaScript functions with facilities for composition and currying.
<!--more-->





To use the monad constructor, you can require it using node:
		
		var f = require("../library/f")

Where the `../` is the location of the module.

Then you will be able to construct functions line this
	
		var plus_1 = f( (num) => num+1 )


After you do that, you will still be able to use `plus_1` like a normal function, but you can also do the following:



Currying
----
When you call a function `f` with less arguments that it accepts, it returns a partially applied
(bound) version of itself that may at any time be called with the rest of the arguments.



		const add3 = f( (a,b,c) => a+b+c )
		
		const add2 = add3(0)
		assert.equal( add2(1, 1), 2 )
		assert.equal( add2(5, 5), 10 )

		const plus10 = add2(10)
		assert.equal( plus10(5), 15 )
		assert.equal( plus10(10), 20 )





`of(value)`
----
If called with a value as an argument, it constructs a function that always returns that value.
If called without arguments it returns a function that always returns the arguments given to it.


		const returns9 = f().of(9)
		assert.equal( returns9(3), 9 )
		assert.equal( returns9("a"), 9 )

		const id = f().of()
		assert.equal( id(3), 3 )
		assert.equal( id("a"), "a" )



`map(funk)`
----
Creates a new function that calls the original function first, then calls `funk` with the result of the original function as an argument:


		
You can create a Function Monad by passing a normal JavaScript function to the constructor (you can write the function directly there):
		
		var plus1 = f( num => num+1 )


Then making another function is easy:

		var plus2 = plus1.map(plus1) 

		assert.equal( plus2(0), 2 )
		
		var plus4 = plus2.map(plus2)

		assert.equal( plus4(1), 5 )





`phatMap(funk)`
----
Same as `map` except that if `funk` returns another function it returns a third function which:
1. Calls the original function first.
2. Calls `funk` with the result of the original function as an argument
3. Calls the function returned by `funk` with the same argument and returns the result of the second call.



You can use `phatMap` to model simple if-then statements. The following example uses it in combination of the currying functionality:
		
		var concat = f( (str1, str2) => str1 + str2)

		var makeMessage = f(parseInt, 1)
			.flatMap((num) => isNaN(num)? f("Error. Not a number") : concat("The number is ") )
		
		assert.equal(makeMessage("1"), "The number is 1")
		assert.equal(makeMessage("2"), "The number is 2")
		assert.equal(makeMessage("Y"), "Error. Not a number")



`phatMap` is similar to the `>>=` function in Haskell, which is the building block of the infamous `do` notation
It can be used to write programs without using assignment.	

For example if we have the following function in Haskell:

		addStuff = do  
			a <- (*2)  
			b <- (+10)  
			return (a+b)
		
		assert.equal(addStuff(3), 19)


When we desugar it, this becomes:

		addStuff = (*2) >>= \a ->
				(+10) >>= \b ->
					return (a+b)

or in JavaScript terms:



		var addStuff = f( num => num * 2 )
			.flatMap( a => f( num => num + 10 )
				.flatMap( b => f.of(a + b) ) 
			)
		
		assert.equal(addStuff(3), 19)




under the hood
--------------
Let's see how the type is implemented










the `of` method, takes a value and creates a function that returns it.
this is very useful if you have a API which expects a function, but you want to feed it with a value (see the `flatmap` example). 

		//a.of(b) -> b a
		of: val => val === undefined ? id : f( () => val ),

`map` just wires the original function and the new one together:

		//(a -> b) => (b -> c) => a -> c
		map: function(funk){ 
			if(funk === undefined){throw new TypeError}
			return f( (...args) => funk( this(...args) ), this._length ) 
		},

`flat` creates a function that: 
1. Calls the original function with the supplied arguments
2. Calls the resulting function (and it has to be one) with the same arguments

		//(b -> (b -> c)) => a -> b
		flat:function(){
			return f( (...args) => this(...args)(...args), this._length ) 
		},

finally we have `tryFlat` which does the same thing, but checks the types first. The shortcut to `map().tryFlat()` is called `phatMap` 

		tryFlat:function(){
			return f( (...args) => {
				var result = this(...args)
				if(typeof result !== 'function'){
					return result
				}else{
					return result(...args)
				}
			}) 
		}

	})

This is the function constructor. It takes a function and adds an augmented function object, without extending the prototype

	var f = (funk = id, length = funk.length, initial_arguments = []) => {

		//We expect a function. If we are given another value, lift it to a function
		if(typeof funk !== 'function'){
			return f().of(funk)
		
		//If the function takes just one argument, just extend it with methods and return it.
		}else if ( length < 2 ){
			return extend(funk, f_methods)

		//Else, return a curry-capable version of the function (again, extended with the function methods)
		}else{
			var extended_funk = extend( (...args) => {
				var all_arguments  = (initial_arguments).concat(args)	
				return all_arguments.length>=length?funk(...all_arguments):f(funk, length, all_arguments)
			}, f_methods)
			
			extended_funk._length = length - initial_arguments.length
			extended_funk._original = funk

			return extended_funk
		}
	}

Here is the function with which the function object is extended

	function extend(obj, methods){
		return Object.keys(methods).reduce(function(obj, method_name){obj[method_name] = methods[method_name]; return obj}, obj)
	}

	
	f.of = val => f( () => val ),

The library also features a standard compose function which allows you to map normal functions with one another

	f.compose = function(){

		//Convert functions to an array and flip them (for right-to-left execution)
		var functions = Array.prototype.slice.call(arguments).reverse()
		//Check if input is OK:
		functions.forEach(function(funk){if(typeof funk !== "function"){throw new TypeError(funk+" is not a function" )}})
		//Return the function which composes them
		return function(){
			//Take the initial input
			var input = arguments
			var context
			return functions.reduce(function(return_result, funk, i){ 
				//If this is the first iteration, apply the arguments that the user provided
				//else use the return result from the previous function
				return (i ===0?funk.apply(context, input): funk(return_result))
				//return (i ===0?funk.apply(context, input): funk.apply(context, [return_result]))
			}, undefined)
		}
	}



