Writings on software engineering.
Back in my first Chiron article, I made a bit of a mistake. I started with all the things
that scare off new functional programmers. Things like >>= and monads. We're going to take a step
back from that precipice and talk about the json{} computation expression.
In general, computation expressions are a bit of syntactic sugar that F# provides. Internally, the
monadic functions of Bind and Return are used, but that is generally transparent to the
user of a computation expression.
Let's dive straight into an example from the first article:
1: 2: 3: |
|
Now, using the json{} compuation expression, let's add the ToJson and FromJson functions:
1: 2: 3: 4: 5: 6: 7: 8: 9: |
|
Compared to the previous example, I think this is way more understandable on its face.
There are no custom operators to figure out, and you don't need to open Chiron.Operators to use it.
So, what do the various parts mean? What's that let! and do!? For a fuller explanation of computation
expressions in general, I'll point you to the excellent introduction by Scott Wlaschin on fsharpforfunandprofit.com.
Nonetheless, let's briefly break this down.
1:
|
|
The first line that we will look at is from the FromJson function. In this case, we are reading the name member
from the hidden Json object. This deserialization may or may not be successful. Presuming that it is successful, we
want the value to be bound to n, but if it fails, we want to short-circuit and report the error.
The key to making this work is the ! in let!. The ! provides a signal to the F# compiler that what we really want
is the string from the Json<string> returned by Json.read. Chiron's json{} implementation of provides such a
bind function which takes care of unwrapping the deserialized value, or in case deserialization fails, triggers the
short-circuit to return the deserialization error.
1:
|
|
Things are subtly different in the ToJson function. In this case, we are updating the hidden Json object being
held by the computation expression. The write doesn't return anything meaningful but it does have a return type of
Json<unit>. The above is syntactically equivalent to:
1:
|
|
The do! just plain looks better than binding to an ignored value.
In the long-promised next article, we'll finally delve into dealing with missing data and union types.