A Progression of Purity

Let's implement a simple multiplication function in different languages, and examine the implications of each type.

JavaScript

function multiply(x, y) {
  console.log('multiplying', x, 'and', y);
  return x * y;
}

Let's find out what its type is.

console.log(typeof multiply);
// function

Welp, that doesn't tell us a whole lot.

Here's what we know from the type:

Here's what we don't know from the type:

Scala

def multiply(x: Int, y: Int): Int = {
  println(s"multiplying ${x} and ${y}")
  x * y
}

Let's find out what type it is.

:t multiply _
// (Int, Int) => Int

This tells us a bit more.

Here's what we know from the type:

Here's what we still don't know from the type:

Haskell

multiply :: Int -> Int -> Int
multiply x y = x * y

We've declared its type to be Int -> Int -> Int. This tells us quite a lot.

Here's what we know from the type:

Here's what we still don't know from the type:

Linear Haskell

multiply :: Int -o Int -o Int
multiply x y = x * y

In addition to the above, here's what we know from the type:

From the type, we don't know how the arguments are used (i.e. whether they are multiplied), but we do know that they are both used, and that they are each used only once.