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;;