Property Based Testing in F# using conditional parameters - unit-testing

I am currently writing a property based test to test a rate calculation function in f# with 4 float parameters, and all the parameters have specific conditions for them to be valid (for example, a > 0.0 && a < 1.0, and b > a). I do have a function checking if these conditions are met and returning a bool. My question is, in my test code using [Property>] in FsCheck.Xunit, how do I limit the generator to test the codes using only values meeting my specific conditions for the parameters?

If you are using FsCheck then you can use the Gen.filter function and the Gen.map function.
Lets say you have this function funToBeTested that you are testing, that requires that a < b:
let funToBeTested a b = if a < b then a + b else failwith "a should be less than b"
And you are testing the property that funToBeTested be proportional to the inputs:
let propertyTested a b = funToBeTested a b / 2. = funToBeTested (a / 2.) (b / 2.)
You also have a predicate that checks the condition requirements for a & b:
let predicate a b = a > 0.0 && a < 1.0 && b > a
We start by generating float numbers using Gen.choose and Gen.map, this way already produces values only from 0.0 to 1.0:
let genFloatFrom0To1 = Gen.choose (0, 10000) |> Gen.map (fun i -> float i / 10000.0 )
Then we generate two floats from 0 to 1 and filter them using the predicate function above
let genAB = Gen.two genFloatFrom0To1 |> Gen.filter (fun (a,b) -> predicate a b )
Now we need to create a new type TestData for using those values:
type TestData = TestData of float * float
and we map the resulting value to TestData
let genTest = genAB |> Gen.map TestData
Next we need to register genTest as the generator for TestData for that we create a new class with a static member of type Arbitrary<TestData>:
type MyGenerators =
static member TestData : Arbitrary<TestData> = genTest |> Arb.fromGen
Arb.register<MyGenerators>() |> ignore
finally we test the property using TestData as the input:
Check.Quick (fun (TestData(a, b)) -> propertyTested a b )
UPDATE:
An easy way to compose different generators is using gen Computation Expression:
type TestData = {
a : float
b : float
c : float
n : int
}
let genTest = gen {
let! a = genFloatFrom0To1
let! b = genFloatFrom0To1
let! c = genFloatFrom0To1
let! n = Gen.choose(0, 30)
return {
a = a
b = b
c = c
n = n
}
}
type MyGenerator =
static member TestData : Arbitrary<TestData> = genTest |> Arb.fromGen
Arb.register<MyGenerator>() |> ignore
let ``Test rate Calc`` a b c n =
let r = rCalc a b c
(float) r >= 0.0 && (float) r <= 1.0
Check.Quick (fun (testData:TestData) ->
``Test rate Calc``
testData.a
testData.b
testData.c
testData.n)

The answer by #AMieres is a great explanation of everything you need to solve this!
One minor addition is that using Gen.filter can be tricky if the predicate does not hold for a large number of elements that your generator produces, because then the generator needs to run for a long time until it finds sufficient number of valid elements.
In the example by #AMieres, it is fine, because the generator generates numbers in the right range already and so it only checks that the second one is larger, which will be the case for about half of the randomly generated pairs.
If you can write this so that you always generate valid values, then that's a bit better. My version for this particular case would be to use map to swap the numbers so that the smaller one is always first:
let genFloatFrom0To1 = Gen.choose (0, 10000) |> Gen.map (fun i -> float i / 10000.0 )
let genAB = Gen.two genFloatFrom0To1 |> Gen.map (fun (a, b) -> min a b, max a b)

Related

Is there a way to put two actions as a result of then in the if - else statement?

I want to make two results in if~~then~~.
For example,
fun count (x,[]) = 0
| count (x,y::ys) =
val cnt = 0
if x mod y = 0 then **/ cnt+1 and count(x,y/2) /**
else count (x-y,ys)
If the if statement is true, as in **/ /**, is there a way to make it do two things?
I want to make two results in if~~then~~ [...]
You can make a function that returns two results by using a tuple, e.g.:
(* Calculate the two solutions of a 2nd degree polynomial *)
fun poly (a, b, c) =
let val d = b*b - 4.0*a*c
val sqrt_d = Math.sqrt d
in ( (~b + sqrt_d) / (2.0*a), (~b - sqrt_d) / (2.0*a) )
end
And you can also deliver two different results depending on some criterion, e.g.:
fun poly (a, b, c) =
let val d = b*b - 4.0*a*c
val sqrt_d = Math.sqrt d
val root_1 = (~b + sqrt_d) / (2.0*a)
val root_2 = (~b - sqrt_d) / (2.0*a)
in
if root_1 > root_2
then (root_1, root_2)
else (root_2, root_1)
end
But if you need for a function to return one result in one situation, and two results in another situation, you need to wrap the result in a return type that can hold either one or two values, e.g.:
datatype ('a, 'b) one_or_two = One of 'a | Two of 'a * 'b
datatype item = Apple | Lamp | Knife
val gen = Random.newgen ()
fun loot () =
if Random.random gen > 0.90
then Two (Lamp, Knife)
else One Apple
You may also read the following StackOverflow Q&A: Multiple if statemens in one Function in SML

tuple access: Can't find a fixed record type

I wrote a function that is supposed to receive a list of tuples. I access the components of the tuples with # and the code compiles:
fun recheck ([], n) = []
| recheck (h::t, n) =
if ((#1 h) * (#1 h)) + ((#2 h) * (#2 h)) = n then
h::recheck(t, n)
else
recheck(t, n)
But another function that basically does the same thing, namely receiving a list of tuples and accessing those, causes an error.
fun validate ([]) = true
| validate (h::t) =
if 1 = (#1 h) then
true
else
false
Can't find a fixed record type. Found near #1
What is the difference here and why does the latter cause an error?
Edit
The first function actually does not compile on its own.
But this entire snippet does:
fun drop ([], n) = []
| drop (h::t, 0) = h::t
| drop (h::t, n) =
drop(t, n-1)
fun sts_linear (y, n) =
if y < (Math.sqrt(n)+1.0) then
let
(* x^2 + y^2 = n => x = sqrt(n-y^2) *)
val x = Math.sqrt(n - (y * y));
val xr = Real.realRound(x);
in
if (abs(x - xr) < 0.000000001) then
[(Real.trunc xr, Real.trunc y)]#sts_linear (y+1.0, n)
else
(
[]#sts_linear (y+1.0, n)
)
end
else []
fun recheck ([], n) = []
| recheck (h::t, n) =
if ((#1 h) * (#1 h)) + ((#2 h) * (#2 h)) = n then
h::recheck(t, n)
else
recheck(t, n)
fun sts (n) =
(
let
val pairs = sts_linear(0.0, Real.fromInt n);
in
recheck(drop(pairs, Real.ceil( Real.fromInt (length(pairs))/2.0 ) ), n)
end
)
Your first code doesn't compile, at least with SML/NJ:
If you got it to compile then it must have been in a nonstandard extension of SML.
The problem with both of your definitions is that there is no polymorphic idea of a tuple of arbitrary arity in SML. You can write functions to work on lists of pairs. You can write functions to work on lists of triples. But -- you can't write functions to work simultaneously on lists of pairs and lists of triples (at least if your function tries to do things with these pairs/triples as tuples).
One solution is to get rid of # and use pattern-matching to extract the components:
fun validate [] = true
| validate ((x,y)::t) =
if x = 1 then
true
else
false
But, if you really want to write a function which can polymorphically apply to either lists of pairs or list of triples (or quadruples,...), the easiest thing to do is to represent the pairs, triples, etc. as lists rather than tuples. Lists which contains lists of nonspecified size are not a problem in SML.
Trying to minimize this down, as I have seen the following work in SML/NJ
and i'm not aware of it actually being a compiler extension
val p1 = {x=0, y=0};
val p2 = {x=1, y=1};
val p3 = {x=1, y=1, z=1};
There is an awkward construct from a compiler error perspective
not many languages have errors that work in this fashion,
because the function is valid, but produces a type error
unless an invocation of the function exists to resolve the
type of 'record', thus to resolve the error more code must be added.
fun getFoo(field) = fn record => field record;
Without the following actual calling of the getX
the compiler cannot determine the type of record
of which the complete type information of ALL fields
of the record must be known to the compiler, not just the #x field.
let val getX = getFoo(#x);
val x1 = getX(p1);
val x2 = getX(p2);
val x3 = getFoo(#x)(p3);
in () end;
while the following commented out snippet results in an error because the types of
p1 and p3 are different, and so different invocations of getFoo
are required
(*
let val getX = getFoo(#x);
val x1 = getX(p1);
val x3 = getX(p3);
in () end;
*)
and the following is insufficient since it never resolves the record.
let val getX = getFoo(#x) in () end;

convert a few 2-tuples to a list of lists

this is a question about ocaml lists and tuples. I have some 2-tuples of numbers (either integers or floats) and I want to convert it to a list of lists (with 2 elements). Assuming that I have defined a num type Int of int | Float of float, the conversion should give the following:
((1,1.0),(0.4,1),(0,0)) => [[Int 1;Float 1.0];[Float 0.4; Int 1];[Int 0;Int 0]]
or more precisely
let a = (1,1.0) and b = (0.4,1) and c = (0,0) in
myconversion (a,b,c) ;;
=> [[Int 1;Float 1.0];[Float 0.4; Int 1];[Int 0;Int 0]]
the point being the values a, b, c... are defined in several places in the source files (by people who use different signatures for their tuples).
The difficulty here is that I don't know the types of the elements of the 2-tuples (int or float, that varies depending on the tuple).
Your input data can't be represented in OCaml as you describe it. OCaml is strongly typed. For example, your example input list is an invalid value in OCaml:
# [(1,1.0);(0.4,1);(0,0)];;
Error: This expression has type float but an expression was expected of type
int
So what you describe as the essence of your problem (not knowing the types) is in fact not possible. You'll have to use some other method of representing the input. For example, you could just use floats for everything. Or you could use pairs of strings.
Update
The answer for the rewritten question is the same. In OCaml it's not possible not to know the type of something statically; i.e., at the time you're writing the program (unless it can be any type at all). It's not possible (or necessary) to query the type of something at runtime. So your question doesn't have an answer (at least as far as I can see).
For OCaml, you have to think with the type system rather than against it. After a while you start to really like it (or at least that's how it worked for me). I'd start by writing down the type you want your function myconverstion to have.
Update 2
I'll repeat my advice to treat your inputs as strings. Assuming you've parsed your input up into pairs of strings, here's some code that does what you want:
let myconversion coords =
let c1 s =
if String.contains s '.' then
Float (float_of_string s)
else
Int (int_of_string s)
in
let cp (a, b) = [c1 a; c1 b] in
List.map cp coords
Here's how it works for your input (reinterpreted as strings):
# myconversion [("1", "1.0"); ("0.4", "1"); ("0", "0")];;
- : fi list list = [[Int 1; Float 1.]; [Float 0.4; Int 1]; [Int 0; Int 0]]
Update 3
Here's some (crude) code that parses a file of numbers into coordinates represented as pairs of strings. It should work as long as the tuples in the input are well formed.
let coords fname =
let ic = open_in fname in
let len = in_channel_length ic in
let buf = Buffer.create 128 in
let () = Buffer.add_channel buf ic len in
let () = close_in ic in
let s = Buffer.contents buf in
let nums = Str.(split (regexp "[^0-9.]+") s) in
let rec mkcoords sofar = function
| [] | [_] -> List.rev sofar
| a :: b :: rest -> mkcoords ((a, b) :: sofar) rest
in
mkcoords [] nums
There are two distinct problems in your setup:
you don't know the type of the tuples parameters
you want to pass them as a single n-ary tuple
For problem 2, you would have to write a function for that type specifically, whereas you could mimic a type level list type by nesting couple of tuples:
myconversion a,(b,c) ;;
The reason is that with that setup, you could write a recursive polymorphic function on the type level list:
val myconversion : type a b. (a,b) -> num list
There would still be a problem on the last element though.
So, assuming that you could pass a sequence to your conversion function, and have it process elements of that sequence one by one, you would still need to find a way of selecting the proper function of pair conversion from the tuple type: that's basically ad-hoc polymorphism, ie. you would need to be able to overload a function on its parameters' types(1). Unfortunately, OCaml doesn't support that out of the box.
One possibility would be perhaps (I have no experience doing that) to implement an extension which would extract the type information of a given expression, and generate the correct code to process it in your own code.
A flexible technique consists in having that extension generate an algebraic description of the tuples types, and use that description as an equality witness in the code which will process the tuples:
type _ w =
| U : (unit * unit) w
| IF : 'a w -> ((int * float) * 'a) w
| FI : 'a w -> ((float * int) * 'a) w
(* other constructors if necessary *)
(* data *)
let a = 1,1.0
let b = 2.0, 2
let c = 3.0, 3
let d = 4, 4.0
let l = a,(b, (c,(d,((),()))))
(* witness *)
let w = IF (FI (FI (IF U)))
(* the type parameter of w should be the same as l type *)
let rec conv : type a b. (a * b) w -> (a * b) -> num list = fun w (x, xs) ->
match w with
U -> []
| IF w' -> let i,f = x in (Int I)::(Float f)::(conv w' xs)
(* etc *)
Here, we encode the type level nil list as (unit * unit) w.
A coalgebraic approach would require to register function overloads to the conversion function polymorphic signature within the extension, and let it pick the right one from the function overload dictionary.
There's a discussion on that topic on the LtU site.
Thanks to everybody who answered. I finally found a solution, using a bit of magic:
# type num = Int of int | Float of float;;
# let to_num x = if Obj.is_int (Obj.repr x) then
Int (Obj.magic (Obj.repr x) : int)
else
Float ((Obj.magic (Obj.repr x) : float));;
# let pair_to_num (a,b) = [to_num a; to_num b];;
# let myconversion (a,b,c) = [pair_to_num a; pair_to_num b; pair_to_num c];;
and the test:
# myconversion ((1,1.0),(0.4,1),(0,0));;
- : num list list = [[Int 1; Float 1.]; [Float 0.4; Int 1]; [Int 0; Int 0]]
# myconversion ((0,0),(1,1.0),(0.4,1));;
- : num list list = [[Int 0; Int 0]; [Int 1; Float 1.]; [Float 0.4; Int 1]]
Magic, the order does not matter and the type is recorded! I can then follow didier's idea to get rid of the pair of superfluous parentheses.

Implementing a counter in SML

I am trying to solve a polynomial evaluation problem on SML, here is the current code I have:
fun eval (nil, b:real) = 0.0
| eval(x::xs, a:real) =
let val y:real = 0.0
fun inc z:real = z+1.0;
in
(x*Math.pow(a,(inc y))) + eval(xs,a)
end;
The problem with this is that it only increments y once, is there a way to have y start at 0 and keep increasing by 1 with every recursion?
You can do that by using the concept of local function (or helper functions). Here's the code :
local
fun helper(nil,b:real,_)=0.0
|helper(x::xt,b:real,y)=(x*(Math.pow(b,(y)))) + helper(xt,b:real,y+1.0)
in
fun eval(x,a:real)= helper(x,a,0.0)
end
I Hope this can solve your problem :)
y is set to be 0 in the let expression inside your function, so every time you call that function it has the value 0. If you want to have a different value for y for different calls to the eval function then you should make it a parameter of that function.
If the xs are supposed to be coefficients in increasing order:
fun eval'( nil, a, n) = 0.0
| eval'(x::xs, a, n) = x*Math.pow(a, n) + eval'(xs, a, n + 1.0)
fun eval(xs, a) = eval'(xs, a, 0.0)
Or, since a is actually constant across the recursion:
fun eval(xs, a) =
let
fun eval'( nil, n) = 0.0
| eval'(x::xs, n) = x*Math.pow(a, n) + eval'(xs, n + 1.0)
in
eval'(xs, 0.0)
end
Or if you don't want to write the recursion youself:
fun eval(xs, a) = foldl (fn(x, (s, n)) => (x*Math.pow(a, n) + s, n + 1.0)) (0.0, 0.0) xs

A List processing problem in F#

I am trying to do problem 12 in Project Euler.
numDivisor64 is to calculate number of divisors.
I wrote this F# code:
let problem12 =
{1L..300000L} |> Seq.map (fun x->x*(x+1L)/2L) |> Seq.map numDivisor64 |> Seq.filter (fun x->x>500L)
The problem asks to find the number rather than its # of divisors. Besides writing this in a less compact way using loops or recursion, any beautiful method?
Another problem, I occasionally find that I need to convert a 32-bit int version of code to a 64-bit one by adding 'L' to all the numbers. Is there a way to avoid this? Anything like c++ template?
I first wrote
let numDivisor n =
let rec countd n d =
if n%d=0 then
let n2, cnt = countd (n/d) d
n2, cnt+1
else
n, 0
let rec collect n d =
if n < d then 1
elif n%d=0 then
let n2, cnt = countd n d
(cnt+1) * (collect n2 d)
else
collect n (d+1)
collect n 2
Later I found I need bigger integers:
let numDivisor64 n =
let rec countd n d =
if n%d=0L then
let n2, cnt = countd (n/d) d
n2, cnt+1L
else
n, 0L
let rec collect n d =
if n < d then 1L
elif n%d=0L then
let n2, cnt = countd n d
(cnt+1L) * (collect n2 d)
else
collect n (d+1L)
collect n 2L
I would rephrase the search for the first wanted number as follows:
start with an infinite stream of int64's
turn them into triangle numbers
find the first number that satisfies the condition (instead of mapping to the number of divisors, which is not what you want, you want the number itself).
code:
let problem12 =
Seq.initInfinite int64 //the same as Seq.initInfinite (fun n -> int64 n)
|> Seq.map (fun x -> x*(x+1L)/2L)
|> Seq.find (fun x -> numDivisor64 x > 500L)
Regarding the second problem: when I solve project Euler problems I usually use int64's by default, because of type inference restrictions.
It's possible to write a more generic version using the inline keyword. See for instance this thread over at hubFS.
EDIT: here's a more generic version, using the technique described in the above link:
The type signature of NumDivisorG becomes horrible, but should work for any data type that 'knows' *,+,1 and 0.
module NumericLiteralG =
let inline FromZero() = LanguagePrimitives.GenericZero
let inline FromOne() = LanguagePrimitives.GenericOne
let inline numDivisorG n =
let rec countd n d =
if n%d=0G then
let n2, cnt = countd (n/d) d
n2, cnt+1G
else
n, 0G
let rec collect n d =
if n < d then 1G
elif n%d=0G then
let n2, cnt = countd n d
(cnt+1G) * (collect n2 d)
else
collect n (d+1G)
collect n (1G+1G)
let problem12L =
Seq.initInfinite int64 //the same as Seq.initInfinite (fun n -> int64 n)
|> Seq.map (fun x -> x*(x+1L)/2L)
|> Seq.find (fun x -> numDivisorG x > 500L)
let problem12I =
Seq.initInfinite id //the same as Seq.initInfinite (fun n -> n)
|> Seq.map (fun x -> x*(x+1)/2)
|> Seq.find (fun x -> numDivisorG x > 500)
if you have the list of divisors you could write a function to calculate the lowest common multiple of them all (which should be the number in question).
in haskell this looks like
lcmAll = foldl1 lcm
in F# i think it would look like this
let rec lcmAll ( head :: tail ) =
Seq.fold lcm head tail
I'm not sure if F# has a builtin lcm.
The alternative to this is to carry the original number around through all the transformations by using a product type, or tuple.
let problem12 =
{1L..300000L} |> Seq.map (fun x->x*(x+1L)/2L) |> Seq.map (fun x->(x,numDivisor64 x)) |> Seq.filter (fun (x,y)->y>500L)
In regards to the 64 bit number issue, if you give your function an explicit type signature it could force F# to use 64-bit ints (provided the type signature is valid for the function definition). Again this sort of thing works in Haskell, I cannot confirm it does with F#. If you could double check that would be awesome.