
Expressing Business Flows Using an F# DSL - jnovino
https://medium.com/jettech/microservices-to-workflows-expressing-business-flows-using-an-f-dsl-d2e74e6d6d5e
======
pwm
Thanks for the write-up, very interesting! Reading it I had a few questions:

1\. How can DAG based workflows express events that are iterative in nature,
ie. would result in a cycle? For example I have an empty shopping cart as a
start state and I want to put X items in it?

2\. Is undo/rollback possible? If so how does cleanup work and does an
undo/rollback means forking into a new state as opposed to going back to a
previous state we logically want to be in?

~~~
Smaug123
cart { let! item1 = item let! item2 = anotherItem … }

No cycle there! You'd use some kind of state monad to keep track, and each
let! simply adds something to the state. For example, you could end up with
the computation expression producing a `Cart = Cart of Item list`, which
contains a list of the things that were added.

Your question about going back to a previous state: it depends on what style
you're using.

* At my day job, we use the "initial algebra" style (which is something of an abuse of F#'s type system but which gives you absolute power). In this style, your computation expression produces a structure isomorphic to a list of "this was added, then this was added, then this was removed, then this was added, …". It is then the job of some further processing step to convert this into more useful forms, like deduplicating carts which have the same contents.

* One could instead produce the cart as you went, and it would Just Work (tm). Note that in F#, most data structures are immutable, so "rolling back" to the list [item1; item2] from the list [item3; item1; item2] is _exactly the same_ as taking the tail of that input list. You won't fork the state by producing another list which happens to have the same contents; they are the same list. In general, F# structures tend to do structural equality.

~~~
pwm
Sorry, I probably wasn't clear in my initial question. What I meant is how do
DAG based workflows deal with computational graphs that contains cycles? Eg.
we have 2 states: Cart and Payment and 2 events: PutItem and Checkout. A
simple (external) DSL describing this graph could look like:

    
    
      Cart --PutItem--> Cart
      Cart --Checkout-> Payment
    

Does the workflow engine in the article exclude situations like this?

Regarding forking what I meant is that if you have:

    
    
      A --event--> B
      ^           /
       \--undo---/
    

then if your invariant is to be a DAG then you could "unroll" the cycle into
some new state C that you would make semantically equivalent to A.

    
    
      A --event--> B --undo--> C
    

This works but causes state explosion.

------
DanielBMarkham
This is an excellent article.

The thing I noted that bears true with my experience: it's an evolution. As
you come to understand the business better and better, you naturally evolve
through some of the same steps.

To me, the steps feel something like imperative->repl->functional->pure
functional->microservices->DSLs

I think if you keep to your code budgets at each step of this, it works out
quite nicely. F# is a great tool for this kind of evolution because it's both
multi-paradigm and plugs into a ton of other stuff.

Thanks guys!

ADD: It would be a mistake to read articles like this and jump into a DSL, in
my opinion. I know a lot of guys who read some really cool books out there on
things like DDD and want to start there. What's missing in articles and books
like this is the backstory. These folks ended up where they were and were able
to do what they're doing now because of a ton of learning. Not learning code.
The business, the tech, and the customers all learning from one another. I
don't see any way that this doesn't take a good bit of time.

------
xamlhacker
F# language has a concept called "computation expressions" which are related
to monads. They are also sometimes called workflows. But the article is using
"workflow" in the more common language way which was confusing to me at first.

~~~
willtim
IIRC they are essentially Monads, but someone decided that was too scary a
name. The result is confusion for experienced programmers, ironically the ones
more likely to use F# (!)

