I'm wondering about how you would make the types work for an async computation graph where the computations aren't simple arithmetic.
The concrete application would be the startup process of a web service where we want to do as much setup as possible to discover config failures before actually acquiring certain resources. In essence you have setup tasks, some of which depend on each other. For example, maybe there's a message queue that you don't want the service to read from unless it has a distributed lock, but you don't want it to acquire this lock until you're sure that everything else is ready to go. During a rolling update you'd like the service to do as much setup as possible to discover any configuration errors before it acquires the lock. You might want to ensure that you can establish connections to other services, a database, etc before acquiring this lock.
The sketch I have in my mind is a directed acyclic graph (DAG) in which each node is a future that takes the resolved values of other nodes as inputs. One simplification is that you don't need to be able to remove nodes from the graph since this graph is constructed statically, used once at startup, and then can be thrown away.
What I'm not sure about is how the types work out. I imagine the constructor for a node would take a list of input nodes and a closure that produces a future. When you evaluate a node its future resolves to whatever the closure produces, and this value is passed to the nodes that depend on it. How do you make the types work when each node can have an arbitrary number of inputs?