I just wrote a fuzz test that basically checks that two calls to the same function with different inputs yields different results. I would like to tell Elm-test that the inputs are not allowed to be equal; otherwise this testcase has a low probability of failing.
I do not want to make them not equal by deriving the second input from the first as this severely limits the search space.
How do I tell the Elm-test fuzzer that the two inputs it generates must not be equal?
EDIT:
Here's one of the sanity tests I wrote:
fuzz3 Fuzz.string Fuzz.int Fuzz.int "Decryption is not possible with wrong key" <|
\msg keySeed keySeed2 ->
let
key =
createKey keySeed
key2 =
createKey keySeed2
in
let
encryptedMessage =
encrypt key msg
in
Expect.equal Nothing (decrypt key2 encryptedMessage)
You can create a fuzzer that generates a tuple with unique values like this:
uniqueTuple : Fuzzer comparable -> Fuzzer (comparable, comparable)
uniqueTuple fuzzer =
let
uniquer (a, b) =
if a == b then
tuple (constant a, fuzzer)
|> Fuzz.andThen uniquer
else
constant (a, b)
in
tuple (fuzzer, fuzzer)
|> Fuzz.andThen uniquer
The idea is that it takes an existing fuzzer (like int), then generates a tuple. If the two values are equal, it keeps the first and tries to generate a new fuzzed value for the second. It recursively does this until the values are different.
You can run a test on just the fuzzer alone with this:
fuzz (uniqueTuple int) "All pairs are unique" <|
\(a, b) ->
Expect.notEqual a b
Related
I want to learn Elm and currently I want to create a random List with tuples containing an index and a random number.
My current approach is to create a list and for each element create a random value:
randomList =
List.map randomEntry (List.range 0 1000)
randomEntry index =
let
seed = Random.initialSeed index
randomResult = Random.step (Random.int 1 10) seed
in
(index, Tuple.first randomResult)
But this only creates even numbers.
Why does it always create even numbers and what is the correct way of doing this?
Strange - using your randomEntry function, the first odd numbers don't start showing up until 53668, and then it's odd numbers for a while. An example from the REPL:
> List.range 0 100000 |> List.map randomEntry |> List.filter (\(a,b) -> b % 2 /= 0) |> List.take 10
[(53668,35),(53669,87),(53670,1),(53671,15),(53672,29),(53673,43),(53674,57),(53675,71),(53676,85),(53677,99)]
: List ( Int, Int )
Now I can't tell you why there is such stickiness in this range (here's the source for the int generator if you're curious), but hopefully I can shed some light on randomness in Elm.
There is really no way to create a truly random number generator using standard computing technology (quantum computers aside), so the typical way of creating randomness is to provide a function that takes a seed value, returns a pseudo-random number and the next seed value to use.
This makes random number generation predictable, since you will always get the same "random" number for the same seed.
This is why you always get identical results for the input you've given: You are using the same seed values of 0 through 1000. In addition, you are ignoring the "next seed" value passed back from the step function, which is returned as the second value of the tuple.
Now, when dealing with random number generators, it is a good rule of thumb to avoid dealing with the seed as much as possible. You can write generators without referring to seeds by building on smaller generators like int, list, and so on.
The way you execute a generator is either by returning a Cmd generated from Random.generate from your update function, which leaves the responsibility of deciding which seed to use to the Elm Architecture (which probably uses some time-based seed), or you can pass in the seed using Random.step, which you've done above.
So, going back to your original example, if you were to write a generator for returning a list of random numbers of a certain size, where each number is within a certain range, it could look something like this:
randomListGenerator : Int -> (Int, Int) -> Random.Generator (List Int)
randomListGenerator size (low, high) =
Random.list size (Random.int low high)
Executing this using step in the REPL shows how it can be used:
> initialSeed 0 |> step (randomListGenerator 20 (1, 10)) |> Tuple.first
[6,6,6,1,3,10,4,4,4,9,6,3,5,3,7,8,3,4,8,5] : List Int
You'll see that this includes some odd numbers, unlike your initial example. The fact that it is different than your example is because the generator returns the next seed to use each consecutive step, whereas your example used the integers 0 through 1000 in order. I still have no explanation to your original question of why there is such a big block of evens using your original input, other than to say it is very odd.
What I've done (with some help from a friend) is create a function that takes a List, Int for the index, and a function to be applied to the element at the specified index. It's similar to Map but instead of applying a function to every element, it applies it to only one element.
So my questions are:
Does this function already exist in the core somewhere? We couldn't find it.
If not, is there a better way of accomplishing this than how we have done it?
Here's the code:
import Html exposing (text)
main =
let
m = {arr=[1,5,3], msg=""}
in
text (toString (getDisplay m 4 (\x -> x + 5)))
type alias Model =
{ arr : List (Int)
, msg : String
}
getDisplay : Model -> Int -> (Int -> Int) -> Model
getDisplay model i f =
let
m = (changeAt model.arr i f)
in
case m of
Ok val ->
{model | arr = val, msg = ""}
Err err ->
{model | arr = [], msg = err}
changeAt : List a -> Int -> (a -> a) -> Result String (List a)
changeAt l i func =
let
f j x = if j==i then func x else x
in
if i < (List.length l) && i >= 0 then
Ok(List.indexedMap f l)
else
Err "Bad index"
NOTE: Elm discourages indexing Lists, as they are linked lists under the hood: to retrieve the 1001th element, you have to first visit all 1000 previous elements. Nonetheless, if you wanted to do it, this is one way.
List.indexedMap is a good way to do what you're describing.
However, since you mention the downside of having to visit all preceding elements in a list, the reality in your example is actually a little worse, if indeed you are super worried about performance.
Your list is actually traversed fully at least two times, regardless of whether the index exists or not. The simple act of asking for the length of a linked list has to traverse the entire list. Check out the source code, length is implemented in terms of a foldl.
Furthermore, List.indexedMap traverses the entire list at least once. I say, at least once, since the source of indexedMap also calls the length function in addition to using map. If we're lucky, the length call is memoized (I'm not familiar enough with Elm internals to know whether it is or not, hence the at least comment). The map itself traverses the entire list when called, unlike Haskell which evaluates things lazily, only as much as necessary.
And if you use indexedMap, the whole list is indexed regardless of the position you are interested in. That is, even if you want to apply the function at index zero, the entire list is indexed.
If you actually want to reduce the number of traversals to a minimum, you're going to (at this time) have to implement your own function and you'll have to do it without relying on length or indexedMap.
Here is an example of a changeAt function which avoids unnecessary traversals and if it finds the position, it stops traversing the list.
changeAt : List a -> Int -> (a -> a) -> Result String (List a)
changeAt l i func =
if i < 0 then
Err "Bad Index"
else
case l of
[] ->
Err "Not found"
(x::xs) ->
if i == 0 then
Ok <| func x :: xs
else
Result.map ((::) x) <| changeAt xs (i - 1) func
It's not terribly pretty, but if you want to avoid unnecessarily walking through the list - multiple times - then you might want to go with something like this.
You're looking for the set function for Arrays. Instead of using a List, which is inefficient as you described, this structure is better suited to your use case.
Here's an efficient implementation of the function you're looking for:
changeAt : Int -> (a -> a) -> Array a -> Array a
changeAt i f array =
case get i array of
Just item ->
set i (f item) array
Nothing ->
array
Also note that the data structure is the last argument in this implementation.
Array is mentioned in the link in your question, but nobody on this thread had explicitly mentioned this option yet.
I'm really loving Elm, up to the point where I encounter a function I've never seen before and want to understand its inputs and outputs.
Take the declaration of foldl for example:
foldl : (a -> b -> b) -> b -> List a -> b
I look at this and can't help feeling as if there's a set of parentheses that I'm missing, or some other subtlety about the associativity of this operator (for which I can't find any explicit documentation). Perhaps it's just a matter of using the language more until I just get a "feel" for it, but I'd like to think there's a way to "read" this definition in English.
Looking at the example from the docs…
foldl (::) [] [1,2,3] == [3,2,1]
I expect the function signature to read something like this:
Given a function that takes an a and a b and returns a b, an additional b, and a List, foldl returns a b.
Is that correct?
What advice can you give to someone like me who desperately wants inputs to be comma-delineated and inputs/outputs to be separated more clearly?
Short answer
The missing parentheses you're looking for are due to the fact that -> is right-associative: the type (a -> b -> b) -> b -> List a -> b is equivalent to (a -> b -> b) -> (b -> (List a -> b)). Informally, in a chain of ->s, read everything before the last -> as an argument and only the rightmost thing as a result.
Long answer
The key insight you may be missing is currying -- the idea that if you have a function that takes two arguments, you can represent it with a function that takes the first argument and returns a function that takes the second argument and then returns the result.
For instance, suppose you have a function add that takes two integers and adds them together. In Elm, you could write a function that takes both elements as a tuple and adds them:
add : (Int, Int) -> Int
add (x, y) = x+y
and you could call it as
add (1, 2) -- evaluates to 3
But suppose you didn't have tuples. You might think that there would be no way to write this function, but in fact using currying you could write it as:
add : Int -> (Int -> Int)
add x =
let addx : Int -> Int
addx y = x+y
in
addx
That is, you write a function that takes x and returns another function that takes y and adds it to the original x. You could call it with
((add 1) 2) -- evaluates to 3
You can now think of add in two ways: either as a function that takes an x and a y and adds them, or as a "factory" function that takes x values and produces new, specialized addx functions that take just one argument and add it to x.
The "factory" way of thinking about things comes in handy every once in a while. For instance, if you have a list of numbers called numbers and you want to add 3 to each number, you can just call List.map (add 3) numbers; if you'd written the tuple version instead you'd have to write something like List.map (\y -> add (3,y)) numbers which is a bit more awkward.
Elm comes from a tradition of programming languages that really like this way of thinking about functions and encourage it where possible, so Elm's syntax for functions is designed to make it easy. To that end, -> is right-associative: a -> b -> c is equivalent to a -> (b -> c). This means if you don't parenthesize, what you're defining is a function that takes an a and returns a b -> c, which again we can think of either as a function that takes an a and a b and returns a c, or equivalently a function that takes an a and returns a b -> c.
There's another syntactic nicety that helps call these functions: function application is left-associative. That way, the ugly ((add 1) 2) from above can be written as add 1 2. With that syntax tweak, you don't have to think about currying at all unless you want to partially apply a function -- just call it with all the arguments and the syntax will work out.
I have a deeply nested datastructure with floats all over the place.
I'm using FsCheck to check if the data is unchanged after serializing and then deserializing.
This property fails, when a float is either NaN or +/- infinity, however, such a case doesn't interest me, since I don't expect these values to occur in the actual data.
Is there a way to prevent FsCheck from generating NaN and infinities?
I have tried discarding generated data that contains said values, but this makes the test incredibly slow, so slow in fact, that the test is still running while I'm writing this, and I have my doubts it will actually finish...
For reflectively generated types that contain floats (as I suspect you're using) you can overwrite the default generator for floats by writing a class as follows:
type Overrides() =
static member Float() =
Arb.Default.Float()
|> filter (fun f -> not <| System.Double.IsNaN(f) &&
not <| System.Double.IsInfinity(f))
And then calling:
Arb.register<Overrides>()
Before FsCheck tries to generate the types; e.g. in your test setup or before calling Check.Quick.
You can check the result of the register method to see how it merged the default arbitrary instances with the new ones; it should have overridden them.
If you are using the xUnit extension you can avoid calling the Arb.register by using the Arbitraries argument of PropertyAttribute:
[<Property(Arbitraries=Overides)>]
As Mauricio Scheffer said, you can use NormalFloat type in test parameter.
Simple example for list of floats:
open FsCheck
let f (x : float list) = x |> List.map id
let propFloat (x : float list) = x = (f x)
let propNormalFloat (xn : NormalFloat list) =
let x = xn |> List.map NormalFloat.get
x = f x
Check.Quick propFloat
//Falsifiable, after 18 tests (13 shrinks) (StdGen (761688149,295892075)):
//[nan]
Check.Quick propNormalFloat
//Ok, passed 100 tests.
I'm using QuickCheck to do generative testing in Clojure.
However I don't know it well and often I end up doing convoluted things. One thing that I need to do quite often is something like that:
generate a first prime number from a list of prime-numbers (so far so good)
generate a second prime number which is smaller than the first one
generate a third prime number which is smaller than the first one
However I have no idea as to how to do that cleanly using QuickCheck.
Here's an even simpler, silly, example which doesn't work:
(prop/for-all [a (gen/choose 1 10)
b (gen/such-that #(= a %) (gen/choose 1 10))]
(= a b))
It doesn't work because a cannot be resolved (prop/for-all isn't like a let statement).
So how can I generate the three primes, with the condition that the two latter ones are inferior to the first one?
In test.check we can use gen/bind as the bind operator in the generator monad, so we can use this to make generators which depend on other generators.
For example, to generate pairs [a b] where we must have (>= a b) we can use this generator:
(def pair-gen (gen/bind (gen/choose 1 10)
(fn [a]
(gen/bind (gen/choose 1 a)
(fn [b]
(gen/return [a b]))))))
To satisfy ourselves:
(c/quick-check 10000
(prop/for-all [[a b] pair-gen]
(>= a b)))
gen/bind takes a generator g and a function f. It generates a value from g, let's call it x. gen/bind then returns the value of (f x), which must be a new generator. gen/return is a generator which only generates its argument (so above I used it to return the pairs).