Design by Contract with F#
By Laurent Le Brun on Wednesday, March 26 2008, 23:06 - [EN] F# articles - Permalink
This article presents a way to get design by contract in F#. Preconditions and postconditions may be grouped at the beginning of the function.
Some languages natively support design by contract features. F# includes an "assert" function. But this function is quite "imperative": it returns a unit type, which is not very nice in a functional code.
The following "ensure" function is easier to integrate in functional code. For example, it's easier to test return values (postconditions) with this function:
[fsharp] let ensure f x = assert (f x) x let positive x = x >= 0 let rec fibo = function | 0 | 1 -> 1 | n -> fibo (n - 1) + fibo (n - 2) |> ensure positive
In Eiffel and in some other languages, preconditions and postconditions are grouped in the code, in order to make them more visible. It is possible to get a similar result with F#.
Let's define precondition and postcondition functions.
[fsharp] let postcondition cond f x = let res = f x assert (cond res) res let precondition cond f x = assert (cond x) f x
You can then add conditions to existing functions:
[fsharp] let checked_abs = abs |> postcondition positive
Here is a way to add conditions when defining a function. You can put as many conditions as you want, you can even call the famous memoize function:
[fsharp] // note: ^< is right associative // <| may become right associative in a future release of F#. let (^<) = (<|) let rec fibo = precondition positive ^< postcondition positive ^< memoize ^< function | 0 | 1 -> 1 | n -> fibo (n - 1) + fibo (n - 2)
I think this is a good example to show how high-order functions may greatly factor code. There's one limitation with the example: functions have only one argument. But it's easy to find a work around, let's define a curry function:
[fsharp] let curry f x y = f (x, y) let rec foo = curry ^< precondition (fst >> positive) ^< precondition (snd >> positive) ^< postcondition positive ^< fun (x, y) -> // ... foo 4 2
Comments
I encourage you to look at:
Contracts for Higher-Order Functions
Robert Bruce Findler and Matthias Felleisen
ICFP 2002
citeseer.ist.psu.edu/find...
You might also be interested in my SML library for higher-order contracts. You can see the signature at mlton.org/cgi-bin/viewsvn... .