Skip to content

Instantly share code, notes, and snippets.

@masaeedu
Last active August 13, 2020 09:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masaeedu/bded64beab7a232493c084e059dd4267 to your computer and use it in GitHub Desktop.
Save masaeedu/bded64beab7a232493c084e059dd4267 to your computer and use it in GitHub Desktop.
fp.nix
{ pkgs }:
let
lib = pkgs.lib;
trace = builtins.trace;
show = builtins.toJSON;
perturb =
let
nix = pkgs.fetchurl {
url = https://raw.githubusercontent.com/kolloch/nur-packages/master/lib/rerun-fixed.nix;
sha256 = "0k1x1vrg6sfw3sayzxm5h07b54k5xafxshi6b48cxi0z8gjjhhpl";
};
in
c: (import nix { inherit pkgs lib; }).rerunOnChange { preOverrideAttrs = _: { ____irrelevant = c; }; };
equality = {
default = { equals = x: y: x == y; };
};
fn = {
id = x: x;
compose = f: g: x: f (g x);
uncurry = f: list.foldl (p: c: p c) f;
curry = n: f:
let go = a: acc:
if a == 0
then f acc
else x: go (a - 1) (list.snoc acc x);
in go n [];
};
id = {
map = f: x: f x;
pure = x: x;
lift2 = f: x: y: f x y;
};
str = {
empty = "";
append = x: y: x + y;
};
list = rec {
nil = [];
cons = x: xs: [ x ] ++ xs;
match = { nil, cons }: xs:
if xs == []
then nil
else match1 { inherit cons; } xs;
match1 = { cons }: xs:
cons (head xs) (tail xs);
snoc = xs: x: xs ++ [ x ];
head = lib.lists.head;
tail = lib.lists.tail;
length = lib.lists.length;
map = lib.lists.map;
foldr = lib.lists.foldr;
foldl = lib.lists.foldl;
foldl' = lib.lists.foldl';
foldMap = m: f: foldr (x: m.append (f x)) m.empty;
fold = m: foldMap m fn.id;
traverse = a: f:
foldr (x: a.lift2 cons (f x)) (a.pure nil);
sequence = a: traverse a fn.id;
traverse1 = a: f: match1 {
cons = x:
foldl' (b: v: a.lift2 snoc b (f v)) (a.map pure (f x));
};
sequence1 = a: traverse1 a fn.id;
intersect = lib.lists.intersectLists;
elem = lib.lists.elem;
pure = lib.lists.singleton;
bind = lib.lists.concatMap;
join = bind fn.id;
intersperse = sep: match {
nil = nil;
cons = x: match {
nil = pure x;
cons = y: ys:
cons x (cons sep (intersperse sep (cons y ys)));
};
};
intercalate = m: sep: fn.compose (fold m) (intersperse sep);
};
obj = rec {
empty = {};
assign = k: v: r: r // { "${k}" = v; };
match = { empty, assign }: o:
if o == {}
then empty
else match1 { inherit assign; } o;
match1 = { assign }: o:
let ks = keys o;
k = list.head ks;
v = o."${k}";
r = filter (k': _: k != k') o;
in assign k v r;
keys = builtins.attrNames;
mapWithKey = lib.attrsets.mapAttrs;
map = f: mapWithKey (_: f);
filter = lib.attrsets.filterAttrs;
has = k: o: o ? k;
traverse = a: f:
match {
empty = a.pure empty;
assign = k: v: r: a.lift2 fn.id (a.map (assign k) (f v)) (traverse a f r);
};
sequence = a: traverse a fn.id;
lift2 = f: match {
empty = _: empty;
assign = k: a: as: match {
empty = empty;
assign = k': b: bs:
let rest = lift2 f as bs;
in if k == k'
then assign k (f a b) rest
else rest;
};
};
};
drv = rec {
serialize = x: builtins.toFile "" (builtins.toJSON x);
deserialize = x: builtins.fromJSON (builtins.readFile x);
map = ab: fa:
serialize (ab (deserialize fa));
pure = serialize;
join = deserialize;
};
in
{ inherit trace show perturb fn id str list obj drv; }
@masaeedu
Copy link
Author

masaeedu commented Aug 5, 2020

Example:

nix-repl> lib.show (lib.list.traverse1 lib.obj (x: x) [ { a = 1; b = 4; } { a = 2; b = 3; } ])
"{\"a\":[1,2],\"b\":[4,3]}"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment