Some thoughts on this in no particular order:
Most workflows are a DAG[1], not a graph, this makes them representable as Tuple[List[Step], List[Tuple[Step, List[Step]]]. In other words, (List[Step], Map[Step, Dependencies]), so your example could be
(
(A, B, C, D),
[(A, []),
(B, [A]),
(C, [A]),
(D, [B, C]),
]
)
which is clearer than the graph representation. Notably, your syntax also assumes a DAG, it can't represent a full graph, so the graph syntax is more "powerful". Though unnecessarily so.
The expression-y representation doesn't scale well. If you consider that workflows are mostly linear, but have branches, the syntax you provided gets ugly fast.
If you imagine a workflow for a CI like
Lint -> Build -> Test -> Deploy -> Email
\-> Test_Windows -/
You end up with
Lint (((Build Test) (Build Test_Windows)) (Deploy Email))
This is one of those weird things that is very much not obvious without hindsight, but try describing a workflow with a critical path of length 10 or 15, and some subchains that are mutual but not exactly the same. Formatting the expression based form you suggest quickly becomes a bit of a nightmare. In the extreme, consider representing a git commit graph, which is also a dag, in the various syntaxes proposed. Then consider trying to modify that structure. It's not very ergonomic.
[1]: Anything loopy or graph-requiring should be factored out into its own sub-flow implemented in a turing complete construct. A workflow should be a composition of such turing complete sub pieces.