/
Arbitrary.sv
53 lines (43 loc) · 1.79 KB
/
Arbitrary.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
grammar silver:util:random;
-- TODO: Consider adding a Shrink type class for use in conjuction with Arbitrary in randomized testing.
-- See https://hackage.haskell.org/package/QuickCheck-2.14.2/docs/Test-QuickCheck.html#v:shrink
@{--
- Represents primitive (terminal) types for which arbitrary random values can be generated.
-}
class Arbitrary a {
genArb :: (RandomGen<a> ::= Integer);
}
instance Arbitrary Integer {
genArb = \ _ -> randomRange(-100, 100); -- TODO: Is this a reasonable default? Revisit.
}
instance Arbitrary Float {
genArb = \ _ -> randomRange(-10.0, 10.0); -- TODO: Is this a reasonable default? Revisit.
}
instance Arbitrary Boolean {
genArb = \ _ -> random;
}
instance Arbitrary String {
-- TODO: Is this a reasonable default? Revisit.
genArb = \ depth::Integer -> do {
let chars :: String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()_-+=\\|[]{}/?'\";:,.<>\n\n\n\t\r ";
randChars :: [Integer] <- randomShuffle(concat(repeat(stringToChars(chars), depth / 3)));
len :: Integer <- randomRange(0, max(depth, 1) * 5);
return charsToString(take(len, randChars));
};
}
instance Arbitrary Location {
genArb = \ depth::Integer -> pure(txtLoc("arbitrary at depth " ++ toString(depth)));
}
instance Arbitrary a, Arbitrary b => Arbitrary Pair<a b> {
genArb = \ depth::Integer -> lift2(pair(fst=_, snd=_), genArb(depth), genArb(depth));
}
instance Arbitrary a, Arbitrary b => Arbitrary Either<a b> {
genArb = \ depth::Integer ->
bind(random, \ b::Boolean -> if b then map(left, genArb(depth)) else map(right, genArb(depth)));
}
instance Arbitrary a => Arbitrary [a] {
genArb = \ depth::Integer ->
if depth > 0
then lift2(cons, genArb(depth), genArb(depth - 1))
else pure([]);
}