I'm a beginner to FP and Type-level programming.
I learned Void
and Unit
recently.
Prelude's unit
is defined as {}
in JavaScript.
"use strict";
exports.unit = {};
My question is "Why not null
but {}
?"
Maybe this is a trivial question, but I'd like to learn its philosophy.
From my understanding, unit
corresponds to null
in JavaScript.
For example, I can call a function with no arguments in JavaScript.
// hello :: Void -> String
function hello () {
return "hello"
}
const h1 = hello() // "hello"
// However, I do not have any members of `Void` in PureScript, so I cannot call like above.
If I have to specify some arguments of hello
function, I choose null
rather than {}
.
// hello :: forall a. a -> String
function hello (a) {
return "hello"
}
// 'hello :: Unit -> String'-like
const h1 = hello(null) // "hello"
// undefined also works, but weird to me
const h2 = hello(undefined)
// also works, but weird
const h3 = hello(42)
const h4 = hello({})
const h5 = hello([])
If unit
represents a side-effect, probably is it undefined
or something null
?
// 'log1 :: String -> Effect Void'-like
function log1 (s) {
return s => () => console.log(s) // console.log return undefined
}
// however, function must return a value
// 'log2 :: String -> Effect Unit'-like
function log2 (s) {
return s => () => {
console.log(s) // side-effect
return null
}
}
// foreign Effect.Console.log (ECMAScript-style)
function log3 (s) {
return s => () => {
console.log(s)
return {} // weird to me; it seems like 'return 42'
}
}
Am I missing something?
It doesn't actually matter what value you use for Unit
. {}
is a pretty arbitrary choice - undefined
or null
, or just not returning a value are all fine too if you're writing something in the FFI. Since Unit
is only supposed to have one inhabitant, there's never a time that the actual runtime value for it is examined.
It's quite a long time since the choice of {}
was made - it's probably a historical accident, leftover from the time that all non-Prim
PS values were constructed as anonymous objects.