A data language
Data deserves a language of its own
Finitio is a data definition language. Think “JSON/XML schema”, but the right way — a dedicated type system for describing data, and a theory of information contracts for moving it between programming and exchange languages.
Validating
Suppose we want to capture information about a medical diagnosis for some patient. At left, a typical digital document in JSON. At right, the corresponding Finitio schema.
{
"patient": {
"id": "27b3ceb0-7e10-0131-c9f1-3c07545ed162",
"name": "Marcia Delgados",
"dob": "1975-11-03"
},
"symptoms": [
"Nausea",
"Fever"
],
"temperature": 39.5
}
Temp = <celsius> Real( f | f >= 33.0 and f <= 45.0 )
{
patient : {
id : Uuid,
name : String( s | s.size > 0 ),
dob : Date( d | alive: d.year > 1890 ),
},
symptoms : [ String( s | s.size > 0 ) ],
temperature : Temp
}
Suppose an invalid document comes in. With Finitio, you properly validate input data and get error messages that say exactly what went wrong, and where.
{
"patient": {
"id": "27b3ceb0",
"dob": "1875-11-03"
},
"symptoms": [
"Nausea",
""
],
"temperature": 12.5
}
[patient/id] Invalid value `27b3ceb0` for Uuid
[patient/dob] Invalid value `1875-11-03` for Date (not alive)
[symptoms/1] Invalid value "" for String( s | s.size > 0 )
[temperature] Invalid value 12.5 for Temperature (celsius)
Coercing
Data exchange languages such as JSON impose a very low abstraction level: booleans, strings and numbers. Finitio helps raise the level of discourse, letting you navigate up and down abstraction levels through information contracts.
[
{
"where": "Brussels",
"at": "2014-03-01",
"temperature": 13.5
},
{
"where": "Paris",
"at": "2014-02-27",
"temperature": 12.0
}
]
Measure = .Measure <info> {
where: String,
at: Date,
temperature: Float( f | f >= -40.0 and f <= 50.0 )
}
[Measure]
There are two information contracts at work here. An implicit one, Date,
provided by Finitio itself, and another one, Measure, connecting a tuple
type to a Measure class.
In Finitio-rb, the Ruby binding, loading and dressing the JSON above returns
an array of Measure instances. Dates are coerced along the way:
[
#<Measure:0x007fb5d3a1ba40 @where="Brussels", @at=#<Date: 2014-03-01>, @temperature=13.5>,
#<Measure:0x007fb5d3a16450 @where="Paris", @at=#<Date: 2014-02-27>, @temperature=12.0>
]
What you get
A type is a set of values
No fixed catalogue of booleans, strings and integers. Finitio gives you an abstract way of building information types: subtypes are subsets, supertypes are supersets. That is the whole definition.
Constraints, not just shapes
Attach named predicates to any type. A temperature is not a Real, it is a Real between 33.0 and 45.0 — and when a document fails, the error names the constraint it broke.
Information contracts
Dress low-level exchange data into rich host-language values, and undress it back. JSON has no date type; your program should not have to care.
Tuples, relations, unions, ADTs
Structural types borrowed from the relational model rather than from object orientation, because the goal is to capture information rather than behaviour.
Errors you can act on
Validation reports every problem with the path that located it, so a rejected payload tells you which field, which element, which constraint.
Ruby and JavaScript
finitio-rb implements the full specification. finitio.js brings the same schemas to Node and to the browser — it is what powers the playground on this site.
Write a schema, paste a document
The playground runs finitio.js entirely in your browser. Nothing is sent anywhere.