Bank Kata in PureScript

Posted on March 13, 2019 by Riccardo

Intro

I suck at FP and I desperately need some feedback from you. So please, do not get mad at the code. And double please share feedback if you got any!!

The Kata

Let’s first introduce the kata by copy / pasting from the awesome Kata-Log:

Write a class Account that offers the following methods void deposit(int) void withdraw(int) String printStatement()

An example statement would be:

Date Amount Balance
24.12.2015 +500 500
23.8.2016 -100 400

Types

void deposit(int) and void withdraw(int) are impure functions. In fact, they accept an int and return void. The only way they can do anything useful is to mutate some state.

String printStatement() is impure too. As a matter of fact, it returns a string out of nothing. The only way for it to do anything useful is to access some state. In this post, I’ll implement printStatement as if it was void printStatement(). That is, the function will print the statement in the console. The reason is that I don’t know how to code it otherwise.

One way to read / write state in PureScript is using the state monad transformer (StateT).

Therefore, we will use the following types:

In other words, our three functions will do their thing in the StateT (Array Transaction) Effect Unit environment. In simpler words, each function will be able to manipulate an array of transactions (state), write to console or get datetimes (monadic operations in Effect) and return nothing (Unit) at the end.

And here we have the type for Transaction:

Implementation

Let’s start with deposit:

Since we are in a monadic environment (StateT (Array Transaction) Effect Unit), we open the function with a do.

Then we use nowDateTime :: Effect DateTime to get the current datetime. The only catch here is that we need to first lift nowDateTime in StateT (Array Transaction) Effect Unit. That is because in a do block each monadic operation (i.e. non lets) must all use the same monad. In this case, that means that both lift nowDateTime and modify_ \ts -> ts <> [t] have type StateT (Array Transaction) Effect a.

After that, a deposit with correct timestamp and amount is assigned to t.

Lastly, modify_ is used to access the current state ts(array of transactions) by appending the new transaction t.

withdraw is almost the same:

Finally, we have printStatement:

The first line uses gets to take the state (array of transactions) and run it through toStatement :: Array Transaction -> String. That means gets toStatement has type Effect String and s has type String.

The last line lifts log s :: Effect Unit in StateT (Array Transaction) Effect Unit. In other words, it prints s to the console.

The implementation of toStatement is not that important. Here is an example of that:

Fire it up

Now we can write something like

which has type StateT (Array Transaction) Effect Unit. And we can run that computation with evalStateT. Notice that the following code returns Effect Unit.

Show me the code

And here we have all the code

Outro

If you liked the post and want to help spread the word, please make some noise 🤘 But only if you really liked it. Otherwise, please feel free to comment or tweet me with any suggestions or feedback.

Thanks to Liam Griffin who inspired me to try this exercise in PureScript with his post in Haskell.

Finally, I want to give a shoutout to BusConf and to all the people I’ve met there that showed so much support for my PureScript journey. You are awesome!

If you are hungry for more, see how we can test the code in the followup: Testing Bank Kata in PureScript.