summaryrefslogtreecommitdiff
path: root/nix-turing/io.nix
diff options
context:
space:
mode:
authorstuebinm2021-07-20 20:43:16 +0200
committerstuebinm2021-07-20 20:43:16 +0200
commit3d498c134a9c0ab61c86a233edd0b2eb76ef44eb (patch)
tree944d1735a932ecabe3d07a01b0dcb22d7b12adc8 /nix-turing/io.nix
parentb160fc2033cfa8a356098d962bab790ec273ec03 (diff)
playing around with IO in Nix
Diffstat (limited to 'nix-turing/io.nix')
-rw-r--r--nix-turing/io.nix147
1 files changed, 147 insertions, 0 deletions
diff --git a/nix-turing/io.nix b/nix-turing/io.nix
new file mode 100644
index 0000000..7f904d6
--- /dev/null
+++ b/nix-turing/io.nix
@@ -0,0 +1,147 @@
+#
+# General purpose programming Nix: Plan of attack
+# ===============================================
+#
+# 1. define some nice attrset that all these functions
+# pass to each other implicitely
+# 2. minimise unnecessary build output
+# 3. a monadic do notation taking a list of monad operations?
+# (how to deal with variables?)
+# 4. implement tic tac toe
+#
+# TODO
+# - nicer syntax
+# - put this into a library
+# - make the seed configurable via cli
+# - tic tac toe
+# let
+{ s, ... }: rec {
+ pkgs = import <nixpkgs> {};
+
+ seed = toString s;
+ eval = code: import (pkgs.writeText "code" code);
+
+ pause = idx: prompt: pkgs.stdenv.mkDerivation {
+ name = "sleep-${seed}";
+ src = pkgs.hello;
+ phases = [ "buildPhase" ];
+ buildPhase = ''
+ echo
+ echo
+ echo ${pkgs.lib.escapeShellArg prompt}
+ sleep 2
+ echo waiting 3 ...
+ sleep 2
+ echo waiting 2 ...
+ sleep 2
+ echo waiting 1 ...
+ mkdir -p $out
+ '';
+ };
+
+ pause_and = { prev, idx, inputCounter, ... }: prompt: code: {
+ prev = pkgs.stdenv.mkDerivation {
+ name = "pause_and-${toString idx}";
+ buildInputs = [ ( pause idx prompt ) ];
+ phases = [ "buildPhase" ];
+ src = pkgs.writeText "code" code;
+ buildPhase = ''
+ echo ${if prev != null then prev.outPath else ""}
+ # ${seed}
+ cp $src $out
+ '';
+ };
+ idx = idx;
+ inherit inputCounter;
+ };
+
+ read_input = prompt: realWorld:
+ let nextWorld = pause_and
+ realWorld
+ ''
+ ${prompt}
+ please enter your input in file /tmp/input-${toString realWorld.inputCounter}
+ ''
+ ''
+ with import <nixpkgs> {};
+ lib.readFile
+ "/tmp/input-${toString realWorld.inputCounter}"
+ # ${seed}
+ # ${if realWorld.prev != null
+ then realWorld.prev.outPath
+ else ""}
+ '';
+ in
+ {
+ prev = nextWorld.prev;
+ value = realWorld.value // {
+ input = import nextWorld.prev.outPath;
+ };
+ inputCounter = nextWorld.inputCounter + 1;
+ idx = nextWorld.idx + 1;
+ };
+
+ print = msg: realWorld: {
+ prev = pkgs.stdenv.mkDerivation {
+ name = "log-derivation";
+ phases = [ "print" ];
+ print = ''
+ echo ${pkgs.lib.escapeShellArg msg}
+ echo ${pkgs.lib.escapeShellArg msg} > $out
+ # ${toString realWorld.idx}
+ # ${seed}
+ # ${if realWorld.prev != null
+ then realWorld.prev.outPath
+ else ""}
+ '';
+ };
+ idx = realWorld.idx + 1;
+ inherit (realWorld) inputCounter value;
+ };
+
+ log = msg:
+ print "==============LOG===============\n${msg}";
+
+ initialWorld = {
+ prev = null;
+ idx = 0;
+ inputCounter = 0;
+ value = {};
+ };
+
+ call = realWorld:
+ realWorld.prev;
+
+ assign = name: value: realWorld:
+ realWorld // {value = realWorld.value // {${name} = value;};};
+
+ # the IO monad
+ bind = monadic: operation:
+ monadic // ((operation monadic.value) monadic);
+
+ bindMonadic = operation: monadic:
+ bind monadic operation;
+
+ unit = realWorld: realWorld;
+
+ # basic do notation
+ do = monadic: operations:
+ pkgs.lib.foldl bind monadic operations;
+
+ # flipped version of do for usage in bound
+ doMonadic = operations: monadic:
+ do monadic operations;
+
+ ifThenElse = cond: ifTrue: ifFalse:
+ (v: if cond v
+ then ifTrue v
+ else ifFalse v);
+
+ while = cond: body:
+ (ifThenElse cond
+ (v: doMonadic [
+ body
+ (while cond body)
+ ])
+ (v: unit));
+}