Monads by example

Running :i Monad in ghci yields the following:

class Applicative m => Monad (m :: * -> *) where
  (>>=) :: m a -> (a -> m b) -> m b
  (>>) :: m a -> m b -> m b
  return :: a -> m a
  fail :: String -> m a

It also lists available instances of the Monad type class:

instance Monad m => Monad (WrappedMonad m)
  -- Defined in ‘Control.Applicative’
instance Monad (Either e) -- Defined in ‘Data.Either’
instance Monad [] -- Defined in ‘GHC.Base’
instance Monad Maybe -- Defined in ‘GHC.Base’
instance Monad IO -- Defined in ‘GHC.Base’
instance Monad ((->) r) -- Defined in ‘GHC.Base’
instance Monoid a => Monad ((,) a) -- Defined in ‘GHC.Base’

Concrete type signatures

To understand similarities and differences between various instances of the Monad type class we will take a look at the type signatures of the return, >>= and >> functions for List, Maybe and Either types:

-- Generic
return :: a -> m a

-- List
return :: a -> [a]

-- Maybe
return :: a -> Maybe a

-- Either
return :: a -> Either l a
-- Generic
(>>=) :: m a -> (a -> m b) -> m b

-- List
(>>=) :: [a] -> (a -> [b]) -> [b]

-- Maybe
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b

-- Either
(>>=) :: Either a b -> (b -> Either a c) -> Either a c
-- Generic
(>>) :: m a -> m b -> m b

-- List
(>>) :: [a] -> [b] -> [b]

-- Maybe
(>>) :: Maybe a -> Maybe b -> Maybe b

-- Either
(>>) :: Either a b -> Either a c -> Either a c

Using return with different types

Do you remember how we said "pure lifts a value to a given type" in the previous note? return is a function doing exactly the same thing for the instances of the Monad type class:

-- List
(return 2 :: [Integer]) == [2]
-- Maybe
(return 2 :: Maybe Integer) == Just 2
-- Either
(return 2 :: Either a Integer) == Right 2

Interactive Examples:


Using >>= with different types

>>= also known as bind helps us run monadic actions (values) in sequence by composing them. A value produced by the first one will be passed as an argument to the second.

After actions are defined we will use >>= to sequentially execute our program:

addOne :: (Monad m, Num a) => a -> m a
addOne a = return (a + 1)
-- List
[ ]    >>= addOne == [ ]
[1]    >>= addOne == [2]
[1, 2] >>= addOne == [2, 3]

[ ]    >>= addOne >>= addOne == [ ]
[1]    >>= addOne >>= addOne == [3]
[1, 2] >>= addOne >>= addOne == [3, 4]
-- Maybe
Nothing >>= addOne == Nothing
Just 1  >>= addOne == Just 2

Nothing >>= addOne >>= addOne == Nothing
Just 1  >>= addOne >>= addOne == Just 3
-- Either
Left  1 >>= addOne == Left  1
Right 1 >>= addOne == Right 2

Left  1 >>= addOne >>= addOne == Left  1
Right 1 >>= addOne >>= addOne == Right 3

Iteractive Examples:


Using >> with different types

Similar to the bind operator >> allows us to sequentially compose two actions by ignoring the value produced by the first.

-- List
[ ] >> [ ] == [ ]
[ ] >> [2] == [ ]
[1] >> [ ] == [ ]
[1] >> [2] == [2]
-- Maybe
Nothing >> Nothing == Nothing
Nothing >> Just 2  == Nothing
Just 1  >> Nothing == Nothing
Just 1  >> Just 2  == Just 2
-- Either
Left  1 >> Left  2 == Left  1
Left  1 >> Right 2 == Left  1
Right 1 >> Left  2 == Left  2
Right 1 >> Right 2 == Right 2

Interactive Examples:


I was pretty intrigued when I saw how these methods work. After reading so much about Monads on the internet I was pretty scared of the concept but then — after I started using them — it turned out they aren't as scary as I originally thought.

Let me know on twitter what was your experience - @maciejsmolinski.

Applicatives by example

Running :i Applicative in ghci yields the following:

class Functor f => Applicative (f :: * -> *) where
  pure :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b
  GHC.Base.liftA2 :: (a -> b -> c) -> f a -> f b -> f c
  (*>) :: f a -> f b -> f b
  (<*) :: f a -> f b -> f a

It also lists available instances of the Applicative type class:

instance Applicative (Either e) -- Defined in ‘Data.Either’
instance Applicative [] -- Defined in ‘GHC.Base’
instance Applicative Maybe -- Defined in ‘GHC.Base’
instance Applicative IO -- Defined in ‘GHC.Base’
instance Applicative ((->) a) -- Defined in ‘GHC.Base’
instance Monoid a => Applicative ((,) a) -- Defined in ‘GHC.Base’

Concrete type signatures

To understand similarities and differences between various instances of the Applicative type class we will take a look at the type signatures of the pure, <*> and liftA2 functions for List, Maybe and Either types:

-- Generic
pure :: a -> f a

-- List
pure :: a -> [a]

-- Maybe
pure :: a -> Maybe a

-- Either
pure :: a -> Either l a
-- Generic
(<*>) :: f (a -> b) -> f a -> f b

-- List
(<*>) :: [(a -> b)] -> [a] -> [b]

-- Maybe
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b

-- Either
(<*>) :: Either l (a -> b) -> Either l a -> Either l b
-- Generic
liftA2 :: (a -> b -> c) -> f a -> f b -> f c

-- List
liftA2 :: (a -> b -> c) -> [a] -> [b] -> [c]

-- Maybe
liftA2 :: (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c

-- Either
liftA2 :: (a -> b -> c) -> Either l a -> Either l b -> Either l c

Using pure with different types

pure lifts a value to a given type. The type can be inferred or specified with a type annotation like in the examples below:

-- List
(pure 2 :: [Integer]) == [2]
-- Maybe
(pure 2 :: Maybe Integer) == Just 2
-- Either
(pure 2 :: Either a Integer) == Right 2

Interactive Examples:


Using <*> with different types

In order to use <*> we need to define some functions we want to work with. After they are defined we will apply them to some instances of the Applicative type class:

addOne :: Num a => a -> a
addOne a = a + 1

addTwo :: Num a => a -> a
addTwo a = a + 2
-- List
[      ]         <*> [ ]    == [ ]  
[      ]         <*> [2]    == [ ]
[addOne]         <*> [ ]    == [ ]
[addOne]         <*> [2]    == [3]
[addOne, addTwo] <*> [ ]    == [ ]
[addOne, addTwo] <*> [2]    == [3, 4]
[addOne, addTwo] <*> [2, 3] == [3, 4, 4, 5]
-- Maybe
Nothing     <*> Nothing == Nothing
Nothing     <*> Just 2  == Nothing
Just addOne <*> Nothing == Nothing
Just addOne <*> Just 2  == Just 3
-- Either
Left  addOne <*> Left  2 == Left  addOne
Left  addOne <*> Right 2 == Left  addOne
Right addOne <*> Left  2 == Left  2
Right addOne <*> Right 2 == Right 3

Interactive Examples:


Using liftA2 with different types

To use liftA2 we also need to define a function. The function will accept two parameters and return a single value. After the function is defined we will apply it to some instances of the Applicative type class:

add :: Num a => a -> a -> a
add a b = a + b
-- List
import Control.Applicative (liftA2)

liftA2 add [ ]   [ ]   == []
liftA2 add [1]   [ ]   == []
liftA2 add [1]   [2]   == [3]
liftA2 add [1,2] [2]   == [3,4]
liftA2 add [1,2] [2,3] == [3,4,4,5]
-- Maybe
import Control.Applicative (liftA2)

liftA2 add (Nothing) (Nothing) == Nothing
liftA2 add (Nothing) (Just 2)  == Nothing
liftA2 add (Just 1)  (Nothing) == Nothing
liftA2 add (Just 1)  (Just 2)  == Just 3
-- Either
import Control.Applicative (liftA2)

liftA2 add (Left  1) (Left  2) == Left  1
liftA2 add (Left  1) (Right 2) == Left  1
liftA2 add (Right 1) (Left  2) == Left  2
liftA2 add (Right 1) (Right 2) == Right 3

Interactive Examples:


Applicatives are not scary either. They are pretty useful as you can see above. Let me know on twitter if you have any comments - @maciejsmolinski.

In the next post you will learn about Monads.

Functors by example

Running :i Functor in ghci yields the following:

class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b
  (<$) :: a -> f b -> f a

It also lists available instances of the Functor type class:

instance Functor (Either a) -- Defined in ‘Data.Either’
instance Functor [] -- Defined in ‘GHC.Base’
instance Functor Maybe -- Defined in ‘GHC.Base’
instance Functor IO -- Defined in ‘GHC.Base’
instance Functor ((->) r) -- Defined in ‘GHC.Base’
instance Functor ((,) a) -- Defined in ‘GHC.Base’

Concrete type signatures

To understand similarities and differences between various instances of the Functor type class we will take a look at the type signatures of the fmap and <$ functions for List, Maybe and Either types:

-- Generic
fmap :: (a -> b) -> f a -> f b

-- List
fmap :: (a -> b) -> [a] -> [b]

-- Maybe
fmap :: (a -> b) -> Maybe a -> Maybe b

-- Either
fmap :: (b -> c) -> Either a b -> Either a c
-- Generic
(<$) :: a -> f b -> f a

-- List
(<$) :: c -> [a] -> [c]

-- Maybe
(<$) :: c -> Maybe a -> Maybe c

-- Either
(<$) :: c -> Either a b -> Either a c

Using fmap with different types

In order to use fmap we need to define a function we want to work with. After it is defined we will apply the function to some instances of the Functor type class:

addOne :: Num a => a -> a
addOne a = a + 1
-- List
fmap addOne [ ]       == [ ]
fmap addOne [1]       == [2]
fmap addOne [1, 2, 3] == [2, 3, 4]
-- Maybe
fmap addOne (Nothing) == Nothing
fmap addOne (Just 2)  == Just 3
-- Either
fmap addOne (Left  0) == Left  0
fmap addOne (Right 2) == Right 3

Interactive Examples:


Using <$ with different types

<$ swaps values in the instance of the Functor typeclass and is originally defined as fmap . const.

-- List
1 <$ [ ]     == [ ]
1 <$ [2]     == [1]
1 <$ [1,2,3] == [1,1,1]
-- Maybe
1 <$ (Nothing) == Nothing
1 <$ (Just 2)  == Just 1
-- Either
1 <$ (Left  0) == Left  0
1 <$ (Right 2) == Right 1

Interactive Examples:


It's not as bad as it looks, or is it? Let me know on twitter - @maciejsmolinski.

In the next post you will learn in a similar way about Applicatives.

JavaScript Series: Context in JavaScript Functions

Have you ever noticed this keyword in JavaScript and wondered how it works? Especially in a context of a function - where does its value come from? How can one find it useful?

Calling a simple function

First, let’s bring back our favourite fullName function:


  /**
   * Sample Usage:
   *
   *   fullName({ firstName: 'Jason', lastName: 'Bourne' });
   *   // => 'Jason Bourne'
   *
   */
  function fullName(person) {
    return person.firstName + ' ' + person.lastName;
  }
 

We’ve learned how to execute this function with some parameters already:


  fullName({ firstName: 'Jason', lastName: 'Bourne' });
  // => 'Jason Bourne'

Not scary, right? Is there any other way to call functions? Turns out there is!

Functions can operate with context

Before we move to the more advanced parts, let’s learn how we could get the same results back by calling this function differently:


  fullName.call(null, { firstName: 'Jason', lastName: 'Bourne' });
  // => 'Jason Bourne'


  fullName.apply(null, [{ firstName: 'Jason', lastName: 'Bourne' }]);
  // => 'Jason Bourne'


  fullName.bind(null)({ firstName: 'Jason', lastName: 'Bourne' });
  // => 'Jason Bourne'

Three different ways and same results. Why bother?

Turns out functions can operate with context. We refer to the context via this keyword. In our example, we intentionally ignored the context parameter and used null.

By context, we usually mean that a function is part of something bigger. In such cases, this refers to that bigger thing. Let’s bring an example:


  var person = {
    firstName: 'Jason',
    lastName: 'Bourne',
    fullName: function () {
      return this.firstName + ' ' + this.lastName;
    }
  };

What you see above is a simple object with personal data. You might have noticed already we didn’t use any parameters in the fullName function and I can assure you it still works!


  person.fullName();
  // => 'Jason Bourne' 

How come? Our function knows exactly it is part of the object and easily recognised this refers to the whole person.

Be careful!

While this example works perfectly fine, if we wanted to borrow that function and use it somewhere else, we might lose the context! See:


  // What if I wanted to save a reference to the function
  // and refer it by the other name somewhere else?
  var borrowedFullName = person.fullName;


  borrowedFullName();
  // => 'undefined undefined'
  

Ooops! Something bad happened. Turns out your function is smart enough and looks for something it could attach to. It totally forgot about the person and tried to check what the current context has to offer. Since your global object, usually* window, does not have fullName nor lastName assigned, fullName returned undefined undefined.

Make sure you don’t harm yourself

First of all, functions operating on context should be used carefully. It is a good practice to trigger strict mode in your functions to make sure you don’t accidentally change global variables. here’s how you do it:


  var strictPerson = {
    firstName: 'Jason',
    lastName: 'Bourne',
    fullName: function () {
      'use strict';
      return this.firstName + ' ' + this.lastName;
    }
  };

Besides the variable name, you may notice ‘use strict’ string in your function. This is all it takes to trigger strict mode in your browser. Now the browser will complain when executing borrowed function:

  
  // Borrowed function with strict mode
  var borrowedStrictFullName = strictPerson.fullName;

 
  borrowedStrictFullName();
  // =>
  // TypeError: Cannot read property 'firstName' of undefined
  // at fullName (...)

I can assure you this is good! You’re not going to hurt yourself by accidentally modifying global variables.

Force a context when calling a function

Good, we learned how to make our code a little bit safer. Now it’s time to move on to contexts! Remember how borrowedStrictFullName call threw an error in strict mode? Right, strict mode prevented us from modifying global variables. Does it mean this function is useless? No, it doesn’t! We can use it. Let’s call it with some context!


  borrowedStrictFullName.call({
    firstName: 'Marie',
    lastName: 'Kreutz'
  });
  // => 'Marie Kreutz'

It worked! Our parameter-less function worked with a context we enforced! Are there any alternatives?

  
  borrowedStrictFullName.apply({
    firstName: 'Marie',
    lastName: 'Kreutz'
  });
  // => 'Marie Kreutz'

"I’m confused" you may say. Same results, what’s the point of having two functions that do the very same thing?

The difference is subtle and it does not necessarily relate to context binding. It is the way these functions treat parameters! I’ll give you an example:


  /**
   * Function that adds two numbers:
   * 
   *   add(1, 2); // => 3
   *   add(5, 1); // => 6
   * 
   * No context involved
   */
  function add(a, b) {
    return a + b;
  }

Below you can find the difference between the way call and apply pass parameters to the function:

  
  add(1, 2);
  // => 3
  
  add.call(null, 1, 2);
  // => 3

  add.apply(null, [1, 2]);
  // => 3

As you can see, call takes an undefined number of parameters and invokes the function as you would do it manually. It just takes one extra context parameter that wasn’t really useful in our case.

The difference is that apply takes only two parameters. The second one is an array of parameters that you would normally pass to the function one by one.

"Why does it matter?" you may wonder.

To put it simply, you’re going to use call mostly to invoke a function with a context when you know exactly how many parameters the target function expects and you’ve got these parameters ready to be used.

On the other hand, apply comes in handy when your function accepts any number of parameters or the number of parameters you pass to the function may vary. Here’s a real world use case:


  /**
   * Math.max takes any number of integers
   * and returns the biggest one
   * 
   * You cannot pass an array of integers to it though!
   * It would return a NaN!
   */
  Math.max(1,2,3,5,4); 
  // => 5

  Math.max([1,2,3,5,4]);
  // => NaN

  Math.max.apply(null, [1,2,3,5,4]);
  // => 5
  //
  // It worked!
  // Apply took our array and applied
  // the numbers individually to Math.max for us
  // as if we applied them manually:
  //
  //         [1,2,3,5,4]
  // Math.max(1,2,3,5,4)

Or just assign a context

When does bind come in handy then?

Bind allows us to keep a function as a function. It does not invoke anything. It just takes care of binding either context or parameters or both. It is useful sometimes.

We could use bind to make sure functions we borrowed keep the original context:


  // Keep the context of `person` we borrowed function from 
  var borrowedStrictFullNameWithContext =
      person.fullName.bind(person);


  borrowedStrictFullNameWithContext();
  // => 'Jason Bourne'

See? We just picked a single method from an object and made sure it remembers where it came from by binding a context to it!

Wrapping up

To wrap everything up, here’s how you use call, bind and apply:


  someFunction.call(context, arg1, arg2, ..., argN);
  // => invokes function and returns results

  someFunction.apply(context, [arg1, arg2, ..., argN]);
  // => invokes function and returns results
                               
  someFunction.bind(context, arg1, arg2, ..., argN);
  // => returns a function with context / parameters bound

Further learnings

What’s next? Bind operator can do much more than setting the context. It can produce functions with [parameters bound]https://devdocs.io/javascript/global_objects/function/bind) as well. I’ll leave more advanced exercises with bind as a homework for you.

Good luck experimenting!

* global object - when writing JavaScript in your browser, the context referred by this operator is window. On the other hand, if you’re writing code in Node.js environment, your global object refers to global. What’s more, in strict mode, this refers to undefined if no context is bound. Make sure your functions using this operator always have context bound in strict mode. Otherwise your code might throw type errors, e.g. “TypeError: Cannot read property 'firstName' of undefined".

JavaScript Series: Adventures with Arrays | Reduce

We've learned about filter and map operations on JavaScript arrays already. Our possibilities do not end there, though.

Drawing conclusions

Often, once we mapped and filtered data, we'd like to draw some conclusions. Sometimes it's about taking a sum of all elements, sometimes it's about the average. Other times we'd like to accumulate results, e.g. count the number of occurrences.

What we're aiming to do is converting a collection into a single value. A value that represents our computation.

Reducing collections

Reducing is an operation that does exactly that with collections. It takes an initial value, current element and returns results of your computation. The next iteration starts with previously computed value and the next element. The process goes on until you run out of elements in the collection.

2b187026-6f93-4f74-b90e-e2444e59b8b6

The image above illustrates the process. Given an array of numbers 1, 2 and 3 we iterate over every element.

  • The process starts with an empty sum accumulator so we assign 0 to it. We add it to the first element and the result is 1
  • The next iteration starts with the previous sum which equals 1. We add it to the second element and the result is 3
  • In the final iteration, again we start with a previous sum accumulator which equals 3. We add the last number to it and the final result is 6

And that’s it! We just learned about reducing arrays!

Reducing in JavaScript

In theory this sound simple. Shall we be scared of JavaScript implementation? Not at all!

Like in the previous notes, we’re going to bring a collection of people data first.


  var people = [
    { gender: 'male', born: 1979 },
    { gender: 'female', born: 1976 },
    { gender: 'female', born: 1970 },
  ];

First exercise - count number of people born before 1975:

 
  function countBornBefore1975(sum, person) {
    if (person.born < 1975) {
      return sum + 1;
    }

    return sum;
  }

  
  // Count number of people born before 1975, start with 0
  people.reduce(countBornBefore1975, 0);
  // => 1

The number looks correct. How about counting number of female data records?


  function countFemaleRecords(sum, person) {
    if (person.gender === 'female') {
      return sum + 1;
    }

    return sum;
  }


  // Count number of female records, start with 0
  people.reduce(countFemaleRecords, 0);
  // => 2

Again, the number is correct!

How about solving a little bit more complex problem like getting a number of male and female records? Making two separate reduce operations sound like an option but there must be an easier way to achieve it. Right, there is!


  function countByGender(accumulator, person) {
    if (person.gender === 'male') {
      return {
        male:   accumulator.male + 1,
        female: accumulator.female,
      };
    }

    return {
      male:   accumulator.male,
      female: accumulator.female + 1,
    };
  }


  
  // Accumulate number of male and female records.
  // Use object literal. Start with zeros. 
  people.reduce(countByGender, { male: 0, female: 0 });
  // => { male: 1, female: 2 }

Perfect! As you can see, we can narrow things down not only to numbers, we can construct object literals and arrays out of initial collection as well!

You just learned about reducing arrays in JavaScript. You may perform some amazing computations when using it with map and filter. Full code listing to be found below.


  var people = [
    { gender: 'male', born: 1979 },
    { gender: 'female', born: 1976 },
    { gender: 'female', born: 1970 },
  ];



  function countBornBefore1975(sum, person) {
    if (person.born < 1975) {
      return sum + 1;
    }

    return sum;
  }

  // Count number of people born before 1975, start with 0
  people.reduce(countBornBefore1975, 0);
  // => 1



  function countFemaleRecords(sum, person) {
    if (person.gender === 'female') {
      return sum + 1;
    }

    return sum;
  }

  // Count number of female records, start with 0
  people.reduce(countFemaleRecords, 0);
  // => 2



  function countByGender(accumulator, person) {
    if (person.gender === 'male') {
      return {
        male:   accumulator.male + 1,
        female: accumulator.female,
      };
    }

    return {
      male:   accumulator.male,
      female: accumulator.female + 1,
    };
  }
  
  // Accumulate number of male and female records.
  // Use object literal. Start with zeros. 
  people.reduce(countByGender, { male: 0, female: 0 });
  // => { male: 1, female: 2 }

Now please go and try writing some reduce operations on your own, have fun!