Memoize the hashCode, but notice that Expr is not recursive on itself (only via the Id graph) so it does not have the DAG-exponential-equality-and-hashcode issue that Literal and other DAGs have.
Memoize the hashCode, but notice that Expr is not recursive on itself (only via the Id graph) so it does not have the DAG-exponential-equality-and-hashcode issue that Literal and other DAGs have.
We use a lazy val instead of a val for binary compatibility.
Expr[N, T] is an expression of a graph of container nodes N[_] with result type N[T]. These expressions are like the Literal[T, N] graphs except that functions always operate with an indirection of a Id[T] where N[T] is the type of the input node.
Nodes can be deleted from the graph by replacing an Expr at Id = idA with Var(idB) pointing to some upstream node.
To add nodes to the graph, add depth to the final node returned in a Unary or Binary expression.
TODO: see the approach here: https://gist.github.com/pchiusano/1369239 Which seems to show a way to do currying, so we can handle general arity