Functional Programming with AWS CDK
3 min read, last updated on 2020-12-13
You have been warned. Below, you may read unpragmatic ramblings about types and monads.
I’m joking - we will talk about monads only. 😀
Motivation
As a functional programmer by training and passion, I could not resist and test how AWS CDK cooperates with functional languages.
My choice fell on F# as AWS CDK contains a template for that language, which is available here:
$ cdk init app --language=fsharp
After initialization, we have received a typical F# project for the .NET Core environment. Sweet!
The first experience is excellent. So far, so good.
What You See Is What You Get
The next one wasn’t so pleasant - and that’s not the language’s fault (you will see in the next section why).
The complete source code can be found in my repository with AWS CDK examples. However, let’s focus on the CDK Stack definition:
namespace FSharpCDK
open Utils
open Amazon.CDK
open Amazon.CDK.AWS.S3
type FSharpCDKStack(scope, id, props) as this =
inherit Stack(scope, id, props)
let expireAfter30Days =
LifecycleRule(Enabled = Utils.nl true,
Expiration = Duration.Days(30.0))
let bucketProps =
BucketProps(
Versioned = Utils.nl true,
LifecycleRules = [| expireAfter30Days |],
PublicReadAccess = Utils.nl false,
BlockPublicAccess = BlockPublicAccess.BLOCK_ALL,
RemovalPolicy = Utils.nl RemovalPolicy.DESTROY)
do
Bucket(this, "TestBucket", bucketProps) |> ignore
()
At first sight, it does not look so different from the other languages (and for sure not so different from C#). But, some subtleties are pissing me off:
- Too much
Nullable<T>
- well, this “pattern” from TypeScript leaks here and forces you to do painful conversions usingOption<T>
or helper functions as I did with Utils.nl. - Arrays instead of Lists - sigh, this looks to me as again TypeScript / JavaScript inheritance.
Those elements are connected with the behavior of how SDKs for the other languages are generated. Libraries for the different programming languages are created with JSII, which means that JS definition is the foundation for all other SDKs. For sure, it had to introduce some compromises.
What I Liked Is What You Don’t See
However, the most significant benefit is related to the functional style of programming and type system. Fluency in writing caused by the combination of those two elements is very pleasant. Declarativeness, referential transparency, immutability, and type system itself help with writing more efficiently.
Even that I’m using Visual Studio Code on Linux, still creating smaller and bigger programs felt frictionless. Most of the time, autocompletion and compiler guided me through the whole process.
What about the other functional languages?
Based on my experience, I am sure that the feeling will be similar for Scala or Clojure. You will face the same obstacles (typical interop with Java libraries).
The truth is that if we do not see additional libraries dedicated to cover imperative SDKs, functional programming languages will offer just the traits available in the language itself. In some cases, it may be beneficial, but only if you are familiar with it.
Peeking into declarative (functional) world
I hope this short blog post inspired you to look into the exciting world of functional programming languages. You may ask, why bother - and you are partially right. It was a fun exercise, definitely not pragmatic and not for production use.
However, I would like to encourage you to expand your horizons. You should know why some things are the way they are. And isn’t infrastructure as code all about the declarative approach?