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>
		
			
				
	
	
		
			110 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			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;
 | |
|       }
 | |
|     )
 | |
|   ])
 | |
| ]
 |