Two Track Coding (ROP) For Dummies – Part 2
Pull from my external blog website: http://indiedevspot.azurewebsites.net/2015/01/20/two-track-coding-rop-for-dummies-part-2/#more-4791
Welcome to Part 2! Hopefully you made it through part 1 with no issues. In this part, I will discuss Applicatives, in this scenario, we are doing validation of an entire type, however you can use this method for any sort of processing in the system that returns a result or failure and takes n parameters.
Part 1: Bind
Part 2: Applicatives
Part 3: Options
Top Down View
So lets start off by looking at the end result and break it down from there again.
|1 2 3 4 5 6 7 8 9||
So this should be fairly straight forward, especially if you went through part 1. We have a function, DoStuff, which takes zero parameters, and returns a Result.
- We have two new infix operators <!> (lift) and <*> (apply)
- We have a new function CreateNerd
- We have two new functions succeed and fail
The most logical place to begin is with the first infix operator <!>, or Lift.
|1 2 3 4 5 6 7||
Whew, an easy one! LiftR takes a function (f) and a result. It succeeds f and pipes it into this applyR. So we are lifting the result into this function. We already know the definition for the infix operators.
So what does this mean? Well its easier to really understand this in more context. Succeed simply wraps a value in a Success. fail just wraps a message in a Failure.
|1 2 3 4 5||
You can see that <!> is used only once and to begin with, but only with this CreateNerd function and multiple Apply Functions. So lets take a look at both of those.
|1 2 3 4 5 6 7 8||
So, we can see that Create Nerd simply takes in all of the parameters of a nerd and returns a complete nerd ;). So that means that Apply must be taking all of the functions, aggregating failures and results and either returning a failure list or individual unwrapped values that have been validated! THATS RIGHT! It even gives you errors if you line up incorrect values or don’t have enough functions returning values. (I love Visual Studio).
So lets dig in a little bit more…
|1 2 3 4 5 6 7 8 9 10 11 12 13 14 15||
So the comments explain EXACTLY what is going on, but maybe not quite how I think. In a single parameter instance, makes perfect sense, f is a function, which we wrapped up in a success (see <!>), this is our Success<CreateNerd>. x is the result of our next line, in this instance
we are simply wrapping 1 in a Success. So we apply the function CreateNerd to 1. Well, this isn’t going to work, CreateNerd takes a ton of parameters, this would however work for a function that takes only a single parameter.
Bringing it All Together
This is where <*> saves the day in conjunction with just functions that return result<vals>
|1 2 3 4 5 6 7 8||
So it will take both functions, in our example above, lines 3 and 4. Run both individually and match against a Success. If both are success, it unwraps both successes and then rewraps them together as a success. So we would go from Success<D> Success<A> to Success<D; A>. So <*> allows us to chain multiple functions together, unwrapping each one and Applying the next one to it. We finally lift those into our first function!
Now that was the happy path (I think the more complicated one to think through).
On the unhappy path, it does the same exact thing, but wraps every portion in a Failure, and drops successes and simply returns the Failure List. So if we had the last 3 lines fail with the message [IncorrectEmail], [IncorrectAddress], [IncorrectGameIds], instead of returning a CompleteNerd, we would return a list of FailureMessages wrapped in a Failure result.
So if we think of this in the context of a Web API controller, GET(id), you can do all of the gets, wrapping everything in success or failure. You return a Result to the controller. It matches that against Success or Failure. In the Success case, just send that json back. In a Failure, change your return code, do your logging, map those messages to something user friendly, send some html to inject down with those and call it a day :).
We covered how to use Applicatives and Lifting to deal with validating the construction of a single type. There are other obvious non validation use cases. This is directly useful when building WebAPIs and other single execution pieces of code. The next article will cover dealing with sequences of types.
Again, special shout out to http://fsharpforfunandprofit.com/rop/ and Scott for helping me wrap my brain around this stuff.
Again, you can download the entire script file here: https://onedrive.live.com/redir?resid=478A64BC5718DA47\!299\&authkey=\!ALbqUC1LcqWQevo\&ithint=file%2