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

JavaScript

functionmultiply(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:

multiply is a function

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

Whether multiply takes any arguments

What, if anything, multiply does with applied
arguments

What, if anything, multiply returns

Whether multiply has any side effects, such as
console.log(...) or exec('rm -rf /')

Scala

defmultiply(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:

multiply is a function

multiply takes two Int arguments

multiply returns an Int value

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

What, if anything, multiply does with applied
arguments

Whether multiply has any side effects, such as
println(...) or "rm -rf /"

Haskell

multiply ::Int->Int->Intmultiply 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:

multiply is a function

multiply takes two Int arguments

multiply returns an Int value

multiply has no side effects, such as
putStrLn ... or system "rm -rf /"

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

What, if anything, multiply does with applied
arguments

Linear Haskell

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

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

multiply uses both arguments exactly once

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.