F# List Manipulation and Property-Based Testing with FsCheck

Classified in French

Written on in English with a size of 4.23 KB

F# List Manipulation and Property-Based Testing

This document provides F# code examples demonstrating list manipulation techniques and property-based testing using FsCheck.

Setting up FsCheck

#r "FsCheck";;
open FsCheck;;

Tagged Value Exercises: Some and None

This section explores the use of tagged values (also known as discriminated unions) and the Some and None options in F#.

Defining a Shape Type

type figura =
| Rettangolo of float * float  // base * altezza
| Quadrato of float  // lato
| Triangolo of float * float ;; // base * altezza

Calculating Area with Option Type

let areaOpt fig =
 match fig with
 | Rettangolo (b,h) -> if b>0.0 && h>0.0 then Some (b*h) else None
 | Quadrato (l) -> if l>0.0 then Some (l*l) else None
 | Triangolo (b,h) -> if b>0.0 && h>0.0 then Some ((b*h)/2.0) else None

Printing the Area

let printArea fig =
 let a = areaOpt fig
 match a with
 | None -> "Figura non ben definita"
 | Some x -> "L'area e' " + (string x)

Summing Areas

let sommaArea (fig1, fig2) =
 let a1 = areaOpt fig1
 let a2 = areaOpt fig2
 match (a1,a2) with
 | (Some x, Some y) -> Some (x+y)
 | _ -> None

List Exercises and FsCheck

This section demonstrates various list manipulation functions and their verification using FsCheck.

Removing Even Numbers

let rec rmEven ls =
 match ls with
 | [] -> []
 | x::xs ->
 match x%2 with
 | 0 -> rmEven(xs)
 | _ -> [x]@rmEven(xs)

Removing Odd Numbers

let rec rmOdd ls =
 match ls with
 | [] -> []
 | x::xs ->
 match x%2 with
 | 0 -> [x]@rmOdd(xs)
 | _ -> rmOdd(xs)

Removing Odd Numbers at Odd Positions

let rec rmOddPos ls =
 match ls with
 | [] -> []
 | [x] -> [x]
 | y::(y1::ys) -> [y]@rmOddPos(ys)

Removing Even Numbers at Even Positions

let rec rmEvenPos ls =
 match ls with
 | [] -> []
 | [x] -> []
 | y::(y1::ys) -> [y1]@rmEvenPos(ys)

Splitting a List

let split ls = (rmOddPos(ls),rmEvenPos(ls))

Calculating List Length

let rec lgth ls =
 match ls with
 | [] -> 0
 | x::xs -> 1 + lgth(xs)

Comparing List Lengths

let rec cmpLength (ls0,ls1) =
 let l = lgth ls0 - lgth ls1
 if l=0 then 0 else
 match l<0 with
 | true -> -1
 | false -> 1

Comparing List Lengths (Alternative)

let rec cmpLength1 (ls0,ls1) =
 match (ls0,ls1) with
 | ([],[]) -> 0
 | ([], [a] ) -> -1
 | ( [a] , []) -> 1
 | (x::(x1::xs),y::(y1::ys)) -> cmpLength(xs,ys)
 | (_,_) -> 0

Removing an Element from a List

let rec remove (x, ls) =
 match ls with
 | [] -> []
 | y::ys ->
 match x=y with
 | true -> remove (x,ys)
 | false -> [y] @ remove(x, ys)

Removing Duplicate Elements

let rec removeDup ls =
 match ls with
 | [] -> []
 | y::ys -> [y]@removeDup(remove(y, ys))

Generating a List Down to 0

let rec downto0 n =
 match n=0 with
 | true -> [0]
 | false -> [n]@(downto0 (n-1))

Generating a List Up to 0

let rec upto0 n =
 match n=0 with
 | true -> [0]
 | false -> (upto0 (n-1))@[n]

Property-Based Testing with FsCheck

Property for rmEven and rmOdd

let prop_rmEven (ls : int list) =
 rmEven(rmOdd(ls)) = []
do Check.Verbose prop_rmEven;;

Property for rmOddPos

let prop_rmOddPos (ls : int list) =
 lgth(rmOddPos(ls)) <= (lgth(ls)+1)/2
do Check.Quick prop_rmOddPos;;

Reversing a Split List

let rec reverseSplit (ls0,ls1) =
 match (ls0,ls1) with
 | ([],[]) -> []
 | ([],[a]) -> [a]
 | ([a],[]) -> [a]
 | (x::xs,y::ys) -> [x]@[y]@reverseSplit(xs,ys)
 | (_,_) -> []

Property for split

let prop_split (ls) =
 reverseSplit(split ls) = ls
do Check.Quick prop_split;;

Related entries: