tvl-depot/nix/stateMonad/tests/default.nix
sterni 5e097aa8e9 feat(nix/stateMonad): simple Nix state monad implementation
In the absence of do syntactic sugar relatively tedious to write, but
useful to express certain types of algorithms. I found it useful to
memoize intermediate results as they are calculated in order to avoid
recomputing them later in a drv dependency analyzer I've written.

Change-Id: I47cf3c644a96952c70276c9fa4cb3190b1c1e027
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6828
Autosubmit: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
2022-10-01 17:47:07 +00:00

110 lines
2.8 KiB
Nix

{ depot, ... }:
let
inherit (depot.nix.runTestsuite)
runTestsuite
it
assertEq
;
inherit (depot.nix.stateMonad)
pure
run
join
fmap
bind
get
set
modify
after
for_
getAttr
setAttr
modifyAttr
;
runStateIndependent = run (throw "This should never be evaluated!");
in
runTestsuite "stateMonad" [
(it "behaves correctly independent of state" [
(assertEq "pure" (runStateIndependent (pure 21)) 21)
(assertEq "join pure" (runStateIndependent (join (pure (pure 42)))) 42)
(assertEq "fmap pure" (runStateIndependent (fmap (builtins.mul 2) (pure 21))) 42)
(assertEq "bind pure" (runStateIndependent (bind (pure 12) (x: pure x))) 12)
])
(it "behaves correctly with an integer state" [
(assertEq "get" (run 42 get) 42)
(assertEq "after set get" (run 21 (after (set 42) get)) 42)
(assertEq "after modify get" (run 21 (after (modify (builtins.mul 2)) get)) 42)
(assertEq "fmap get" (run 40 (fmap (builtins.add 2) get)) 42)
(assertEq "stateful sum list"
(run 0 (after
(for_
[
15
12
10
5
]
(x: modify (builtins.add x)))
get))
42)
])
(it "behaves correctly with an attr set state" [
(assertEq "getAttr" (run { foo = 42; } (getAttr "foo")) 42)
(assertEq "after setAttr getAttr"
(run { foo = 21; } (after (setAttr "foo" 42) (getAttr "foo")))
42)
(assertEq "after modifyAttr getAttr"
(run { foo = 10.5; }
(after
(modifyAttr "foo" (builtins.mul 4))
(getAttr "foo")))
42)
(assertEq "fmap getAttr"
(run { foo = 21; } (fmap (builtins.mul 2) (getAttr "foo")))
42)
(assertEq "after setAttr to insert getAttr"
(run { } (after (setAttr "foo" 42) (getAttr "foo")))
42)
(assertEq "insert permutations"
(run
{
a = 2;
b = 3;
c = 5;
}
(after
(bind get
(state:
let
names = builtins.attrNames state;
in
for_ names (name1:
for_ names (name2:
# this is of course a bit silly, but making it more cumbersome
# makes sure the test exercises more of the code.
(bind (getAttr name1)
(value1:
(bind (getAttr name2)
(value2:
setAttr "${name1}_${name2}" (value1 * value2)))))))))
get))
{
a = 2;
b = 3;
c = 5;
a_a = 4;
a_b = 6;
a_c = 10;
b_a = 6;
b_b = 9;
b_c = 15;
c_c = 25;
c_a = 10;
c_b = 15;
}
)
])
]