Let's implement a simple multiplication function in different languages, and examine the implications of each type.
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:
multiply
is a functionHere's what we don't know from the type:
multiply
takes any argumentsmultiply
does with applied
argumentsmultiply
returnsmultiply
has any side effects, such as
console.log(...)
or exec('rm -rf /')
def multiply(x: Int, y: Int): Int = {
println(s"multiplying ${x} and ${y}")
* y
x }
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 functionmultiply
takes two Int
argumentsmultiply
returns an Int
valueHere's what we still don't know from the type:
multiply
does with applied
argumentsmultiply
has any side effects, such as
println(...)
or "rm -rf /"
multiply :: Int -> Int -> Int
= x * y multiply 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 functionmultiply
takes two Int
argumentsmultiply
returns an Int
valuemultiply
has no side effects, such as
putStrLn ...
or system "rm -rf /"
Here's what we still don't know from the type:
multiply
does with applied
argumentsmultiply :: Int -o Int -o Int
= x * y multiply x y
In addition to the above, here's what we know from the type:
multiply
uses both arguments exactly onceFrom 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.