How do I compare Double values in Hunit? - unit-testing

I would like to understand how I can use HUnit to compare Real values, specifically Double. I say errors, as far as I understand HUnit has no standard methods for comparing this type, so I stumbled upon this question:
Testing haskell equality on Doubles with HUnit?
From it I learned that there is Data.AEq, which gives the right comparator -== (the right one as far as I understand it)
But the presence of the comparator does not tell me anything about how to compare with it in HUnit, for example there is such a test:
test1 :: Test
test1 = TestCase (assertEqual "Test linearApproximation" expectedResult (linearApproximation (1, 10) 0.95 points))
where
points = [(1, 2), (2, 3)]
expectedResult = Linear [Just 1.0,Just 1.95,Just 2.9,Just 3.8499999999999996,Just 4.8,Just 5.75,Just 6.699999999999999,Just 7.6499999999999995,Just 8.6,Just 9.549999999999999]
[Just 2.0,Just 2.95,Just 3.9,Just 4.85,Just 5.8,Just 6.75,Just 7.699999999999999,Just 8.649999999999999,Just 9.6,Just 10.549999999999999]
I think it's clear to everyone why I don't like this test, I wish I hadn't written such an exact expectedResult, but I don't understand how I can apply -==
Maybe there is another way?

Here is the way I use. In the tests/ folder I create this module:
module Approx where
-- round x to n digits
approx :: Int -> Double -> Double
approx n x = fromInteger (round $ x * (10^n)) / (10.0^^n)
-- check whether rounded x1 and rounded x2 are equal
approxEqual :: Int -> Double -> Double -> Bool
approxEqual n x1 x2 = approx n x1 == approx n x2
I could do instead, shorter: abs (x1 - x2) < 10.0^^(-n), but I have this approx function for historical reasons.
Then in the Main module, I have for example:
module Main where
import Approx
import Math.NevilleTheta -- this is a module from my package
import Test.Tasty (defaultMain, testGroup)
import Test.Tasty.HUnit (assertBool, testCase)
main :: IO ()
main = defaultMain $
testGroup "Tests"
[ testCase "a theta_c value" $ do
let expected = 0.902705416117337
obtained = theta_c 1.0 2.5
assertBool "" (approxEqual 10 expected obtained)
]
And in the cabal file:
test-suite unit-tests
type: exitcode-stdio-1.0
main-is: Main.hs
hs-source-dirs: tests/
other-modules: Approx
Build-Depends: base >= 4.7 && < 5
, tasty
, tasty-hunit
, jacobi-elliptic
Default-Language: Haskell2010
where jacobi-elliptic is my package.
Alternatively, you could do
assertEqual "" (approx 10 expected) (approx 10 obtained)
This has one advantage: if the equality does not hold, the two different values are printed with the failure notification.
EDIT
I finally wrote a custom "assert" function.
module Approx where
import Test.Tasty.HUnit (Assertion, assertEqual)
-- round x to n digits
approx :: Int -> Double -> Double
approx n x = fromInteger (round $ x * (10^n)) / (10.0^^n)
-- assert approximate equality
assertApproxEqual :: String -> Int -> Double -> Double -> Assertion
assertApproxEqual prefix n x1 x2 =
assertEqual prefix (approx n x1) (approx n x2)
This stuff can be generalized to Num a instead of Double.

Related

How to create a random list in haskell

I'm new to haskell and came across this problem: as the title says, I'm trying to create a list of a given length with random numbers, ranging between some x and y. So for example, if x=0 and y=10, the list would be something like: [0,4,3,8,0,2]. I'd prefer to do it with list comprehension and without any IO's. I've seen some posts about similar topics, but none have been helpful to me so far.
Using System.Random in the random package, this is exactly the function randomRs:
randomRs :: (Random a, RandomGen g) => (a, a) -> g -> [a]
It takes a range of values and a generator and returns a lazy list of random values in that range. You can make a generator from a fixed seed using mkStdGen:
mkStdGen :: Int -> StdGen
For example, here’s a seed that (on my machine, with my particular version of random) coincidentally produces the example values you gave:
> take 6 $ randomRs (0, 10) $ mkStdGen 15915
[0,4,3,8,0,2]
If you want the program to produce different random values on each invocation, you must use IO to seed the random number generator with the current time. For that you can use newStdGen instead:
newStdGen :: IO StdGen
A complete example:
import System.Random (newStdGen, randomRs)
main :: IO ()
main = do
gen <- newStdGen
print $ randomList 6 0 10 gen
randomList
:: (Random a, RandomGen g)
=> Int -> a -> a -> g -> [a]
randomList len lo hi gen = take len $ randomRs (lo, hi) gen
The excellent answer by Jon Purdy solves the problem using library function randomRs. This works fine.
However, there is the drawback that the final state of the random number generator is lost. In the general case, you may have other needs for random numbers, so you need that final state, to use it as the initial state for these other needs.
The loss of the final state is linked to the fact that randomRs provides an unlimited supply of random numbers, so there is no proper final state. But the text of your question mentions “a list of a given length”. So there is no need to use randomRs. Instead, you can use function getRandomR, which returns a single random number, as the basic building block.
The most general way to do this is to use the MonadRandom class with the runRand evaluation function. That gives this sort of source code:
import System.Random
import System.Random.TF -- Threefish algorithm
import Control.Monad.Random
-- monadic action to get *count* random numbers between xmin and xmax
someRandomNumbers :: MonadRandom mr => Int -> Int -> Int -> mr [Int]
someRandomNumbers xmin xmax count =
sequence (replicate count (getRandomR (xmin, xmax)))
main = do
let count = 6
seed = 377708 -- adjusted to get exactly [0,4,3,8,0,2] :-)
randGen0 = mkTFGen seed
action = someRandomNumbers 0 10 count
(xs, randGen1) = runRand action randGen0 -- get final state too
putStrLn $ "random xs = " ++ (show xs)
Program output:
random xs = [0,4,3,8,0,2]
Note 1: instead of the standard generator, I used the Threefish random number generator, because it is known to have better statistical properties.
Note 2: IO is not involved at all, except when finally printing the results.

Property Based Testing in F# using conditional parameters

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)

Haskell list comprehension (print sqrt for element of list)

I have GHCi, version 7.8.3. I would like calculate the sum of the sqrt items, which are divisible by 10.
If I write [ x | x <- [10..100], x `mod` 10 == 0] or sum [sqrt x | x <- [10..100]] is correct.
But if I write sum [ sqrt x | x <- [10..100], x `mod` 10 == 0] when an error is displayed:
'<interactive>:39:1:
No instance for (Show t0) arising from a use of ‘print’
The type variable ‘t0’ is ambiguous
Note: there are several potential instances:
instance Show Double -- Defined in ‘GHC.Float’
instance Show Float -- Defined in ‘GHC.Float’
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
...plus 23 others
In a stmt of an interactive GHCi command: print it'
How to change the command , the program that was correct ?
The problem comes from the fact that when you use mod, the type of the numbers must be Integral a => a, and when you use sqrt the type of the numbers must be Floating a => a. There are no types that GHC knows of that fit both of these constraints, although because you're executing it in GHCi the error message for whatever reason is mostly useless. The error message is like that because GHCi uses print, which calls show, and for some reason that's the first constraint that gets checked. Since there are no types with the constraints Show, Integral, and Floating, it doesn't type check.
Your other two examples typecheck because they only use one of mod or sqrt. You can get the combination of the two to work using fromIntegral before applying sqrt:
sum [sqrt $ fromIntegral x | x <- [10..100], x `mod` 10 == 0]

How to calculate the sine function in Haskell?

Here is my problem: I need a Haskell function that computes an approximation of the sine of some number, using the associated Taylor serie ...
In C++ I wrote this:
double msin(double number, int counter = 0, double sum = 0)
{
// sin(x) = x - (x'3 / 3!) + (x'5 / 5!) - (x'7 / 7!) + (x'9 / 9!)
if (counter <= 20)
{
if (counter % 2 == 0)
sum += mpow(number, counter * 2 + 1) / mfak(counter * 2 + 1) ;
else
sum -= mpow(number, counter * 2 + 1) / mfak(counter * 2 + 1) ;
counter++;
sum = msin(number, counter, sum);
return sum;
}
return (sum* 180.0 / _PI);
}
Now I am trying to do it in Haskell and I have no idea how... For now I was trying something like this (it doesn't really work, but it is work in progress ;) ):
This works:
mfak number = if number < 2
then 1
else number *( mfak (number -1 ))
mpow number potenca = if potenca == 0
then 0
else if potenca == 1
then 1
else (number * (mpow number (potenca-1)))
This doesn't work:
msin :: Double -> Int -> Double -> Double
msin number counter sum = if counter <= 20
then if counter `mod` 2==0
then let sum = sum + (msin 1 (let counter = counter+1 in counter) sum) in sum
else let sum = sum + (msin 1 (let counter = counter+1 in counter) sum) in sum
else sum* 180.0 / 3.14
Updated....doesn't compile :/ "Couldn't match expected type Double' with actual type Int'"
msin :: Double -> Int -> Double -> Double
msin number counter sum = if counter <= 20
then if counter `mod` 2==0
then let sum' = sum + ((mpow number (counter*2+1))/(mfak counter*2+1)) in msin number (counter+1) sum'
else let sum' = sum - ((mpow number (counter*2+1))/(mfak counter*2+1)) in msin number (counter+1) sum'
else sum* 180.0 / 3.14
As you can see, the biggest problem is how to add something to "sum", increase "counter" and go in recursion again with these new values...
P.S. I am new to Haskell so try to explain your solution as much as you can please. I was reading some tutorials and that, but I can't find how to save the result of some expression into a value and then continue with other code after it... It just returns my value each time I try to do that, and I don't want that....
So thanks in advance for any help!
I would rework the algorithm a bit. First we can define the list of factorial inverses:
factorialInv :: [Double]
factorialInv = scanl (/) 1 [1..] -- 1/0! , 1/1! , 1/2! , 1/3! , ...
Then, we follow with the sine coefficients:
sineCoefficients :: [Double]
sineCoefficients = 0 : 1 : 0 : -1 : sineCoefficients
Then, given x, we multiply both the above lists with the powers of x, pointwise:
powerSeries :: [Double] -- ^ Coefficients
-> Double -- ^ Point x on which to compute the series
-> [Double] -- ^ Series terms
powerSeries cs x = zipWith3 (\a b c -> a * b * c) cs powers factorialInv
where powers = iterate (*x) 1 -- 1 , x , x^2 , x^3 , ...
Finally, we take the first 20 terms and sum them up.
sine :: Double -> Double
sine = sum . take 20 . powerSeries sineCoefficients
-- i.e., sine x = sum (take 20 (powerSeries sineCoefficients x))
The problem is expressions like let stevec = stevec+1 in stevec. Haskell is not an imperative language. This does not add one to stevec. Instead it defines stevec to be a number that is one more than itself. No such number exists, thus you will get an infinite loop or, if you are lucky, a crash.
Instead of
stevec++;
vsota = msin(stevilo, stevec, vsota);
You should use something like
let stevec' = stevec + 1
in msin stevilo stevec' vsota
or just
msin stevilo (stevec + 1) vsota
(There's also something here that I don't understand. You are going to need mpow and mfak. Where are they?)
As you can see the biggest problem is how to add something to "vsota",
In a functional language you would use recursion here - the variable vstota is implemented as a function parameter which is passed from call to call as a list is processed.
For example, to sum a list of numbers, we would write something like:
sum xs = go 0 xs
where go total [] = total
go total (x:xs) = go (total+x) xs
In an imperative language total would be a variable which gets updated. Here is is a function parameter which gets passed to the next recursive call to go.
In your case, I would first write a function which generates the terms of the power series:
sinusTerms n x = ... -- the first n terms of x - (x'3 / 3!) + (x'5 / 5!) - (x'7 / 7!) ...
and then use the sum function above:
sinus n x = sum (sinusTerms n x)
You may also use recursive lists definitions to get [x, x^3, x^5 ...] and [1, 1/3!, 1/5! ...] infinite sequences. When they are done, the rest is to multiply their items each by other and take the sum.
sinus count x = sum (take count $ zipWith (*) ifactorials xpowers)
where xpowers = x : map ((x*x)*) xpowers
ifactorials = 1 : zipWith (/) ifactorials [i*(i+1) | i <- [2, 4 .. ]]
Also, it would be better to define xpowers = iterate ((x*x)*) x, as it seems to be much more readable.
I’ve tried to follow your conventions as much as I could. For mfak and mpow, you should avoid using if as it is clearer to write them using pattern matching :
mfak :: Int -> Int
mfak 0 = 1
mfak 1 = 1
mfak n = n * mfak (n - 1)
mpow :: Double -> Int -> Double
mpow _ 0 = 1
mpow x 1 = x
mpow x p = x * mpow x (p - 1)
Before calculating the sinus, we create a list of coefficients [(sign, power, factorial)] :
x - (x^3 / 3!) + (x^5 / 5!) - (x^7 / 7!) + (x^9 / 9!)
→ [(1,1,1), (-1,3,6), (1,5,120), (-1,7,5040), (1,9,362880)]
The list is created infinite by a list comprehension. First we zip the lists [1,-1,1,-1,1,-1...] and [1,3,5,7,9,11...]. This gives us the list [(1,1), (-1,3), (1,5), (-1,7)...]. From this list, we create the final list [(1,1,1), (-1,3,6), (1,5,120), (-1,7,5040)...]:
sinCoeff :: [(Double, Int, Double)]
sinCoeff = [ (fromIntegral s, i, fromIntegral $ mfak i)
| (s, i) <- zip (cycle [1, -1]) [1,3..]]
(cycle repeats a list indefinitely, [1,3..] creates an infinite list which starts at 1 with a step of 2)
Finally, the msin function is near the definition. It also uses a list comprehension to achieve its goeal (note that I kept the * 180 / pi though I’m not sure it should be there. Haskell knows pi).
msin :: Int -> Double -> Double
msin n x = 180 * sum [ s * mpow x p / f | (s, p, f) <- take n sinCoeff] / pi
(take n sinCoeff returns the first n elements of a list)
You may try the previous code with the following :
main = do
print $ take 10 sinCoeff
print $ msin 5 0.5
print $ msin 10 0.5
The expression is of the form x*P(x2).
For maximal efficiency, the polynomial in x2 must be evaluated using the Horner rule rather than computing the powers of x2 separately.
The coefficient serie with the factorial values can be expressed recursively in Haskell, just like is commonly done for the Fibonacci series. Using the ghci interpreter as our testbed, we have:
$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/ :? for help
λ>
λ>
λ> nextCoeffs d c = c : (nextCoeffs (d+1) ((-c)/(fromIntegral $ (2*d+2)*(2*d+3))))
λ>
λ> allCoeffs = nextCoeffs 0 1.0
λ>
where d is the depth inside the serie and c the current coefficient.
Sanity check: the coefficient at depth 3 must be the inverse of 7!
λ>
λ> 1.0 /(allCoeffs !! 3)
-5040.0
λ>
The Horner rule can be rendered in Haskell thru the foldr1 :: (a -> a -> a) -> [a] -> a library function.
As is customary in Haskell, I take the liberty to put the term count as the leftmost argument because it is the one most likely to be held constant. This is for currying (partial evaluation) purposes.
So we have:
λ> :{
|λ> msin count x = let { s = x*x ; cs = take count allCoeffs ;
|λ> stepFn c acc = acc*s + c ; }
|λ> in x * (foldr1 stepFn cs)
|λ> :}
Sanity checks, taking 20 terms:
λ>
λ> pi
3.141592653589793
λ>
λ> msin 20 (pi/6)
0.49999999999999994
λ>
λ> msin 20 (pi/2)
1.0
λ>
Side note 1: final multiplication by 180 / π is only of interest for inverse trigonometric functions.
Side note 2: in practice, to get a reasonably fast convergence, one should reduce the input variable x into the [-π,+π] interval using the periodicity of the sine function.

Haskell: Filter List with those that are Integers

How would I filter a list so that I only return the list of those that are integers?
For example, filtering a list like [1, 1.2, 2, 2.2] would return [1, 2].
Considering your list to be of type [Double] as you can not have (in any simple way) a list with elements of different types.
Once you have a list of double, you can use the function ceiling.
ceiling 2.1 = 3
ceiling 2.0 = 2
so a function to check if a number has no fractional part can be written as
nonFractional d = (fromIntegral $ ceiling d) == d
now you can do filter on this
> filter nonFractional [1, 1.2, 2, 2.2]
[1.0,2.0]
(Edit)
The above approach of comparing equality does not work for large numbers like
> nonFractional (12345678987654321.5)
True
Using #David's idea if you change the definition of nonFractional as
nonFractional d = (fromIntegral $ ceiling d :: Rational) == d
Then it seems to work for large fractions as well
> nonFractional (12345678987654321.5)
True
First of all, your list should be homogenous, so you can't have list of Integers and Doubles.
There is a nice function properFraction, which decomposes a number into its whole and fractional parts:
properFraction :: (Fractional a, Integral b) => a -> (b,a)
So, we can define a function to figure out is number have a non-zero fractional part or not.
> let haveNoFractionalPart = (== 0.0) . snd . properFraction
haveNoFractionalPart :: Double -> Bool
No we can filter your list with that function:
> filter haveNoFractionalPart [1, 1.2, 2, 2.2]
[1.0,2.0]
Update:
I should admit that my solution isn't valid and workable for some cases in the real world. Because of something like
> properFraction (11111111111111111111.1)
(11111111111111110656,0.0)
Anyway, it's hard to imagine the case when it's needed to filter what you calling an Integer from some list of values that you have. And there is no such way to define that any number with floating point have zero floating part with 100% probability.
Maybe some wrapper over Integer and Double will be helpful.
What about this:
filterInt :: (RealFrac a) => [a] -> [Integer]
filterInt [] = []
filterInt (x:xs)
| frac == 0 = a : filterInt xs
| otherwise = filterInt xs
where
(a, frac) = properFraction x
test:
> let li = [1, 1.2, 2, 2.2]
> filterInt li
> [1,2]
A number of solutions have been posted for Rational, where in actuality you really only need to compare the denominator to 1:
hasFraction' :: Rational -> Bool
hasFraction' = (/= 1) . denominator
This can be generalized to any Real and is one of the safest methods to check whether a number has a fractional part:
hasFraction :: (Real a) => a -> Bool
hasFraction = hasFraction' . toRational
That function does not solve the rounding error problem, but that's natural. When rounding errors bother you, you're using the wrong data type.
It depends where you got the data from.
Haskell doesn't let you mix pure integers with non-integers,
so your integers will get tainted with the inaccuracy inherent in data types like Double unless you use something more accurate like Rational,
but given that you don't want the non-integers anyway, throw them away at source, before they're numeric data, if you can.
If you got the data from a user, either use an input form that only allows them to enter sequences of digits, or use getInt below.
If you got the data from a database or other text-based source, use getInt below.
If you got the data from some code you don't control (library or external call), is there an alternative that will give you just integers?
If so, use it, if not, use one of the other rounding-based solutions in the other answers.
getInt converts a String to an Integer, cunningly ignoring anything that isn't an Integer:
import Data.Char (isDigit)
getInt :: String -> Maybe Integer
getInt xs | all isDigit xs = Just (read xs)
| otherwise = Nothing
So getInt "12345" is Just 12345 whereas getInt 12345678987654321.1 is Nothing.
We can use that to remove non-integer input from some list:
getInts :: [String] -> [Integer]
getInts xss = catMaybes $ map getInt xss
or more consisely, we could write
getInts = catMaybes.map getInt.
Now catMaybes :: [Maybe a] -> [a] and it gets rid of the Nothings and unwraps the Justs. We'll need to
import Data.Maybe (catMaybes) at the top to get it.
If your data comes as a floating point number of some sort,
bear in mind there's no true equality in a floating point type,
so even if you convert to a more accurate representation before checking,
it's logically impossible for you to ever know whether the original data
represented an exact integer or just something quite close to an integer
that the floating point representation rounded before the data got to you.
For example:
Prelude> (12345678987654321.6 :: Double) == 12345678987654322.0
True
whereas
Prelude> (12345678987654321.6 :: Rational) == 12345678987654322.0
False
But if you can choose the data type, you're in control of the generating code, so choose not to include non-integers!
Summary: it's easiest to get rid of non-integers before you turn them into numerical data,
and you're not subject to occasional bizzare rounding errors.
Your list will have to be of type [Double] or [Integer], or some other type of number. You cannot mix types.
That said, if you have a list of doubles and you're trying to filter out those that are not integers, you can always use round, floor, or ceiling to check equivalency to the number.
For example:
isInt :: (RealFrac a) => a -> Bool
isInt x = x == (fromIntegral $ round x)
Then you can just filter your data using this, using filter:
filter isInt [1, 1.2, 2, 2.2] -- [1.0, 2.0]