Enter: world wide web, HTTP, browsers

It’s 2011, and we still don’t statically isolate and model different
kinds of data (namely, the rich languages that are HTML/SQL vs
strings), and by association, their properties, and as a result
people suffer. The web is not a nice place.

Enter: WWW/HTTP/Browsers (pt 2.)

A popular technique in mainstream languages for web programming (a la
Rails/Django) is metaprogramming - creating reusable components
based on generating code at runtime.

Studies (2008) have shown that SQL Injection and XSS attacks are two of the
most prevalant vulnerabilities plauging web applications today. Here’s the
TL;DR:

The statistics includes data about 12186 web applications with 97554
detected vulnerabilities of different risk levels. The analysis shows
that more than 13%* of all reviewed sites can be compromised
completely automatically. About 49% of web applications contain
vulnerabilities of high risk level (Urgent and Critical) detected
during automatic scanning (T. 1). However, detailed manual and
automated assessment by white box method allows to detect these high
risk level vulnerabilities with probability up to 80-96%.

Preventing injections manually can already be tough, but ensuring
metaprograms that create code that is immune to vulnerability can be
even more difficult.

Core idea: rich static types that prevent these classes of errors, and
can make sure generated programs also play by the rules.

Ur: what is it?

Ur is a variant of ML, with Haskell-isms. It features, amongst other things:

Modules, Functors

Type classes, Monads

Strict evaluation, pure by default (monads control effects)

Impredicative polymorphism/kind polymorphism

Polymorphic variants

ML syntax (grumble*)

Sports a form of metaprogramming based on row types (see
Mitchell Wand’s paper)

Takes ideas from theorem provers like Coq, and has type level
computation, but not dependence.

Based on System F-omega

* Haskell syntax is the best

Ur/Web: what is it?

Special library and compiler modifications to support building web
applications with Ur.

Typed XML fragments & SQL are part of the language (postgres/sqlite/mysql
backends)

Sports a form of functional reactive programming for client side.
No javascript - everything is written in Ur.

Aims to support high assurance and reusable web development through
statically typed metaprogramming.

Very efficient: implementation does not use garbage collection (a degenerate
form of region inference is used,) and the compiler completely eliminates
all polymorphism through whole program optimization, like MLton.
Main Ur/Web demo server uses less RAM than the bash shell.

Ur/Web: main selling point

Ur’s main selling point is the metaprogramming facilities, and type
level computation which allow you to generate type-safe code - which
still has all the prior safety guarantees - for any given
specialization of a metaprogram.

Note: This isn’t done by type-checking individual instantiations of
a metaprogram. Rather, the metaprogram itself is typed in such a
way as to guarantee correct operation at any possible instantiated
type.

Ask yourself: can template haskell generate code which is not
well-typed, thus causing compilation to fail?

Remember Curry-Howard: types are theorems, and this also goes for
Ur/Web. The type of a metaprogram is a static theory stating any
program that all generated code plays by the rules.

Simple examples: types/polymorphism

All polymorphic type variables in Ur are explicitly declared, but
inferred at use sites. Most polymorphic declarations require full
annotations of this form, as type inference is undecidable.

Simple examples: records

Anonymous records are still there like they are in OCaml or Standard ML, but they’re a bit more powerful
in Ur as we’ll show later. Here we can see two special record operators, -- which is ‘field removal’, and
++ which is ‘record concatenation’.

Simple examples: type classes

funmax [a] (_ : ord a) (x : a) (y : a) : a =
if x < y then
y
else
x

Usage:

max 1 2 == 2

Critical thing to note: the ‘ord a’ constraint is actually a value
parameter to the function, but we never explicitly use it when
calling the function. This is because, like Haskell, type class
constraints are inferred by default. But unlike Haskell, instances are
actually values.

Type class instances are more like value-level witnesses of some
instance, that the compiler infers automatically. We can also provide
an explicit witness:

Simple examples: Modules + type classes (pt 2)

Thanks to the fact that type class instances are really more like
values, it’s possible to create closed type classes in Ur by
simply not exporting a function to construct a new instance. So if we
take the last example and change it:

Metaprogramming fundamentals: types and kinds

In Haskell, you normally have a few basic kinds which quantify
types. In Ur, there are several fundamental kinds, and they’re
important because you end up dealing with them a lot when doing
metaprogramming. The kinds are:

Ur/Web: a challenge to Haskellers

TL;DR: Given is an example of a CRUD demo which allows you to
automatically generate a Rails like ‘scaffold’ - particularly an
administrative CRUD style interface - for any given database table.

The metaprogram is itself typed in such a way to guarantee that
generated programs behave correctly and are immune to generic kinds of
attacks, for any given SQL table. These guarantees apply to both
server side (type-checking queries) and client side (type checking
HTML,) for any and all generated programs.

Challenge: can equivalent functionality be implemented in Haskell?
What’s it look like? Remember, it’s a ‘challenge’ - nobody says it’s
impossible, just that it’s going to be challenging.

Things not covered here

C FFI

JavaScript FFI

Deployment/static file handling

Kind polymorphism

Impredicative polymorphism

Limitations/simply “not your cup of tea”

Mostly designed for apps backed by relational data stores. No
built in key-value/nosql/non-relational support. You could bind
this yourself however.

No package manager. Not many packages at any rate. Neither of
these are good.

Did I mention Haskell-like syntax is the best?

Hard to understand compiler errors.

I’m going to say that again. Hard to understand compiler errors.

Limitations/simply “not your cup of tea”

Arguably, XML fragments as first-class literals in the language is
not the “right way” because programmers don’t write that. You can
abstract over this with modules at the very least. Not pretty but
it does work.

Arguably, literal SQL as part of the language is not the “right
way” because you may inevitably want some other type of data
store. It may also be less convenient than, say, an ORM for
abstraction. You can write your own type-safe ORM however. On the
other hand, who knows when or if non-relational backends
will be supported.

Needs more love and community!

Conclusions

Typed functional programming is great for web dev. Also, lots of options!

Types help in the construction of correct programs in any domain, but…

… the web is particularly suited for it. For every SQL
injection or XSS vulnerability, someone cries because you don’t know
the difference between strings and real data.