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:

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.

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:

`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:

// 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:

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

By Laurent Le Brun, Wednesday 26 March 2008 :: [EN] F# articles :: #32

## Comments

1. On Monday 3 November 2008 at 13:34, by

Vesa Karvonen## Leave a comment

Comments are closed.