I took a quick look through the example for relational extensions. I don't see anything about reading a file, much less
inferring type from a file. Empirical's key innovation is that it can
infer type from an external source so as long as the source can be derived at compile time.
let path = "/path/to/files"
let fname = "quotes.csv"
let quotes = load(path + "/" + fname)
Since load() requires a compile-time parameter, Empirical automatically resolves the file's location ahead of time. Specifically, Empirical determines that the variables are constants and that the plus operator is pure; computing the resulting value has no side effects. Thus, the Empirical compiler accommodates load() by computing the parameter during semantic analysis. This is automatic
compile-time function evaluation.
As for load(), it is a macro whose expansion includes inferring the schema of the table by sampling the first few lines of the file. This is a type provider.
Now contrast that logic against something like Apache Spark. It's written in a statically typed language (Scala), but its table semantics are dynamically typed! That's because Spark holds the schema as a runtime value and addresses column names as strings. Spark's mechanism for inferring type means it can't maintain static typing.
Empirical is the only system I know of that can infer types while staying static.