Comparing wont work since ned and nfx are different kind of fruits, and the comparision function does not type-check. However, here’s a bit of context on the motivation behind it:
Ned uses nix-effects as its stream library, my streams implementation (originally a simple stack-safe loop on rust fx-rs and later ported to) nfx was not stack-safe in nix due not having another way to loop than recursive functions and no tail optimization. The story changed when nix-effects implemented those very same streams nfx had but now on a stack-safe trampoline. My den project since v0.9 had its own modules-independent dependency-injection subsystem, which I later realized was a manual/rigid reader-monad/effect-system, many bugs back then were due to forgetting to do some manual context-threading, so in trying to solve that I wanted to use proper effects, and since I’ve been contributing to nix-effects, Den is using that. Ned was born to explore a way to simplify many of the state handling and simplification to the effects-protocol that Den uses, since streams operations are simple to understand and cycle-like components compose beautifully I tried to explore that kind of architecture to reduce Den inter-components communication. And that is how Ned was born and will later be used to simplify Den internals.
I’m a huge proponent of FRP UI’s taking streams from a functional core. But I’m at a loss to find somewhere where this might be something I’d want to use. Do you have any demos with real-world applications for this? Ps. I read through the documentation and saw your demos and saw nothing I’d apply in the real world. Same with dendric configs actually. Definitely interesting thought experiments.
Hey! sorry for the late reply. I’ve updated the repo readme to state more clearly why I needed Ned -after all I’m sharing things I do as act of giving, they are useful to me and exist for a reason I find sufficient to dedicate time for them-. The Readme has now links showcasing example nixos configs done with Ned (as tests since Ned is not a nixos framework). Maybe a more real world example is the fleet test, that tries to replicate Den quirks (basically hosts providing configuration to each others - - see webservers announcing themselves in an event based fashion to a load balancer automatically) see links on readme.
I thought of a great place for a real-world implementation of your streams idea in the Talos Linux project.
Currently, (and in my opinion not quite approaching the GUIX or NixOS level of build-the-world using your language) they have an image factory repo that will build custom images based on specific settings. https://factory.talos.dev/
If I could instead just define attributes and build an image, that would be a perfect demonstration of this. Selfishly, I intend to do something like this for a raspberry pi5. My current progress using nix to do it is here. Perhaps I could learn how to apply your dendritic approach here to great effect?
Basically, I’m trying to locally and deterministically build a cluster of Pi5’s booting Talos Linux from the SD card (by necessity) and extended to mount 1TB NVME drives on each Pi as clustered storage.
I’m interested to hear how you’d approach it. I think it’s the perfect candidate for that approach since each branch of the tree doesn’t interact; and the difficulty in interaction between each dendrite is the dendritic approach’s main weakness (from what I have come to understand).
can you elaborate on this ? I have not read your code, but just to make a clarification, Ned cycles are just streams, not dendritic (Den is dendritic – but that is a different beast). What you mean by “difficult interaction between each dendrite”.
Here’s another (still very experimental) project using Ned I started today, (it is still TBA when it has better UX story): zen an stream-based module system (Ned cycles are the config fixpoint – and also each submodule is just another cycle, since I added effect-rotation to nix-effects which provide layers of isolation, that is how submodules work on Zen).
I read it as, since they are streams composed at the top level, adding mechanics for them to interrelate to one another are slightly more challenging than other methods simply because of that composability but perhaps I was incorrect.
Thanks for taking the time to explain. I look forward to learning more about it.
Burnt a ton of tokens on trying this out with 5.3-codex (20$/month plan, and needed it to help me figure out how to actually use this thing). Trying to make an actor system.
The interesting thing is that the ned-based actor system is longer than the pure nix one, and still needs to call builtins.genericClosure itself. Feel like I’m doing something wrong with it. About the same performance, too.
Hey @bitbloxhub, so happy to read you trying out this stuff. Just a quick headsup: Zen modules are very very experimental.
Regarding actors, yes I think your agent (not you) is doing something wrong if the ned-based code uses genericClosure that means it is not using effectful streams properly, there should not be need of any use of genericClosure if everything happens within streams.
So, for a Ned based actor system we could have the following considerations for your agent:
Nix is single-threaded (the pure-language interpreter has no way to express concurrency)
This basically reduces Actors to be independent message processing stream-transformers that can keep their own independent state.
Ned (fx-streams) have scanl and fold to have stateful stream reduction.
A Driver is basically stream->stream: A stream transformer that would be the basis for actors.
An important part of Actors is they have Inbox / Behaviour / Identity.
Inbox is basically an messages flowing on an stream.
Behaviour is a receive stream function behaviour :: ST msg -> ST { reply, behaviour } where new-behaviour replaces the current behaviour (a fold), and reply gets flatMapped on the response stream.
Identity is only needed if you want being able to pass actor refs, and you’d have a top-level (or nested) routing behaviour that distributes messages. An alternative is using Ned cycles where you have named-sinks and named-sources and these names act as the “channel” where to communicate, on this second approach a routing top-cycle can use { to: "foo/bar/baz", from, msg } to specify the location of the nested baz cycle where to deliver the message, probably also want to distinguish between ask and tell.
Streams are themselves values, so you can create an stream that flows streams. You could be using this to create 1-1 private channels between actors.
Explore these ideas with your agent. Tell it that it must not force stream evaluations (keep everything inside streams) and force only at the edges of the app. To take a look at Ned cycle nesting tests.
I’d also be interested in having an actor lib built on Ned streams, feel free to join #denful:matrix.org if you’d want to iterate/collaborate with us on it.
Thanks, although zen-testing was a misnomer anyways, as Zen is a very small part of what I was trying out there. Renamed to denful-testing and will keep that in mind about Zen.
That’s a really elegant library! (Really, all your libraries are pretty great, even if I can’t find a use-case for them, or do too much magic for me like Den )
One thing I noticed on the docs site: is svg-zoom.js intentionally supposed to affect ALL svgs or just diagrams? Fun easter egg if so, but was suprised when scrolling on the aside icon.
Thanks! I was amused a the idea of using CSS Selectors when I first saw it when looking at new denful repos, but it looks nice after looking at it some more! Will consider it next time I feel like rewriting/refactoring my configuration, but for now flake-aspects is enough for me (Another one of your libraries!).
This does seem a bit nicer as I can (assuming I’m reading the docs right) make a CSS selector to see if a user has both niri and noctalia-shell and set Noctalia keybinds in Niri without my current method of just checking if the HM Niri options are defined and using mkMerge.
yes, exactly, but these work at meta-level (before nixos module evaluation – nixos eval sees the clean modules already resolved – just like in den). I will use Nest on an old MacbookPro 2011 that I need to use linux on, since it x86_64-darwin is unsupported on nixpkgs now. So I’m also happy to be exploring the usability of this approach and dogfood to find things to improve/fix
btw, you don’t need to rewrite your whole infra to try it, just instead of having the host trait create a nixos instance, just return an { imports = modules; } and mix that with whatever on the right nixosSystem call you are using.
EDIT: we are very off-topic now sorry, we have a thread for Nest, or join at #denful Matrix