Exercises in Programming Style–The One

You can become a serverless blackbelt. Enrol to my 4-week online workshop Production-Ready Serverless and gain hands-on experience building something from scratch using serverless technologies. At the end of the workshop, you should have a broader view of the challenges you will face as your serverless architecture matures and expands. You should also have a firm grasp on when serverless is a good fit for your system as well as common pitfalls you need to avoid. Sign up now and get 15% discount with the code yanprs15!

NOTE : read the rest of the series, or check out the source code.

If you enjoy read­ing these exer­cises then please buy Crista’s book to sup­port her work.

exercises-prog-styles-cover

Fol­low­ing on from the last post, we will look at The One style today.

 

Style 9 – The One

You may also know this style as Monads, which many consider to be a scary word… That said, I know a few smart people who have done excellent talks to explain Monads in a way that’s easy to understand, check out these links:

and this post is probably the best of the lot, especially if you enjoy cartoon drawings!

 

Constraints

  • Existence of an abstraction to which values can be converted
  • This abstraction provides operations to:
    1. wrap around values, so that they become the abstraction
    2. bind itself to functions, so to establish sequences of functions
    3. unwrap the value, to examine the final result
  • Larger problem is solved as a pipeline of functions bound together, with unwrapping happening at the end
  • Particularly for The One style, the bind operation simply calls the given function, giving it the value that it holds, and holds on to the returned value

 

Version 1 (simple bind)

In terms of a port from Crista’s example, most of code is very similar to the Pipeline style, except their return values have to be wrapped into another abstraction.

I thought about this and couldn’t come up with a really meaningful abstraction, so I settled on a single-case Result type:

image

Next, we need to define the ‘bind’ operator (which, the convention is to use >>=):

image

the rest is pretty straight forward (i.e. copy from Pipeline style, add |> Result to end of each function):

image

Before we move on though, I wanna bring your attention to the removeStopWords function briefly:

image

If you recall, readFile now returns a Result<string> so in order to split the wrapped string we’ll need to unbox it first. Since our Result type is single-cased, we can kinda cheat by using pattern matching to extract the wrapped string value out and bind it to the raw value:

image

 

Now, we want to chain the functions together using our bind:

image

Oh no! What’s happening here?!?

Ah, the compiler is telling us that ‘bind’ is expecting a continuation that returns a value wrapped in the Result type but printMe returns unit instead.

That’s a bummer, so we can either rewrite printMe to be compliant of such requirement. Or, we can use another concept that’s commonly used as a ‘lift’:

image

A lift is simply a function that takes a function that returns an unwrapped value, and returns a modified version that returns a wrapped value instead.

image

So with a tiny change, we can make everything work now:image

 

But but but, this is F#, and we have computation expressions, so we can do better than that!

(if you’re totally new to the idea of computation expressions, then I recommend reading at least the first few posts in Scott’s excellent series before proceeding)

 

Version 2 (computation expressions)

Have you read Scott’s introductory posts on computation expressions? Have a basic understanding of how they work?

Good, then let’s continue.

 

Here is a very simple CE that works with the Result type:

image

and now we can use it to refactor the removeStopWords function:

image

Here, return! is translated to the ReturnFrom method in TheOneBuilder and unwraps the Result<string> for us so we don’t need to manually unwrap it with pattern matching.

 

To chain the functions together, we no longer have to use bind and can instead let the CE deal with unwrapping values for us:

image

Also, notice that we no longer have to ‘lift’ the printMe function.


aside : you might also noticed that I’m shadowing previous instances of text, words and wordFreqs as I go. It’s not necessary, and many people would have preferred text’, text’’, etc. instead.

I think in this particular case shadowing actually helps me prevent the accidental misuse of discarded values. E.g. the following would be a bug (and I’ve made this type of mistakes in the past..)

theOne {

    let! text = readFile ”p & p”

    let! text’ = filterChars text

    let! text’’ = normalize text  // should be text’ instead

    …

}


That said, I personally think >>= is still a very useful combinator, and would prefer to write the above as:

image

 

You can find the source code for this exer­cise here (v1) and here (v2).

Liked this article? Support me on Patreon and get direct help from me via a private Slack channel or 1-2-1 mentoring.
Subscribe to my newsletter


Hi, I’m Yan. I’m an AWS Serverless Hero and I help companies go faster for less by adopting serverless technologies successfully.

Are you struggling with serverless or need guidance on best practices? Do you want someone to review your architecture and help you avoid costly mistakes down the line? Whatever the case, I’m here to help.

Hire me.


Skill up your serverless game with this hands-on workshop.

My 4-week Production-Ready Serverless online workshop is back!

This course takes you through building a production-ready serverless web application from testing, deployment, security, all the way through to observability. The motivation for this course is to give you hands-on experience building something with serverless technologies while giving you a broader view of the challenges you will face as the architecture matures and expands.

We will start at the basics and give you a firm introduction to Lambda and all the relevant concepts and service features (including the latest announcements in 2020). And then gradually ramping up and cover a wide array of topics such as API security, testing strategies, CI/CD, secret management, and operational best practices for monitoring and troubleshooting.

If you enrol now you can also get 15% OFF with the promo code “yanprs15”.

Enrol now and SAVE 15%.


Check out my new podcast Real-World Serverless where I talk with engineers who are building amazing things with serverless technologies and discuss the real-world use cases and challenges they face. If you’re interested in what people are actually doing with serverless and what it’s really like to be working with serverless day-to-day, then this is the podcast for you.


Check out my video course, Complete Guide to AWS Step Functions. In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. There is something for everyone from beginners to more advanced users looking for design patterns and best practices. Enrol now and start learning!


Check out my video course, Complete Guide to AWS Step Functions. In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. There is something for everyone from beginners to more advanced users looking for design patterns and best practices. Enrol now and start learning!