I am new to F# and I am still learning. In addition to reading books, articles and taking Plural-site courses I have been working on small projects to learn by coding.
My current project is a tool to help balance a checkbook. A user can enter transactions as bills and deposits which are currently stored in memory as records.
I am currently stuck at how to properly design the adding of transactions to a list and storing that list in FP. In C# I would create an empty list, then every time a user added a bill it would be added to this list. I understand that in FP lists are immutable and that I need to return a new list every time. What I am stuck at is how and where to maintain this list in the program. What I mean is that in C# I would have this list as a property on
a class and maintain that list’s state. How do I do this in FP? Do I have to pass this list to every function? How do I maintain the latest copy of the list in memory as I go through the program. Any advice will help. Thanks
One way you could achieve your goals would be to define a record type that can hold a list of transactions and then define a module to manipulate values of that type (creation, adding transaction, balance…).
type Transaction =
| Debit of float
| Credit of float
type Checkbook = { Transactions: Transaction list }
module Checkbook =
let Empty = { Transactions = [] }
let add tx cb = { cb with Transactions = tx :: cb.Transactions }
let balance cb =
cb.Transactions
|> List.sumBy (function | Debit x -> x | Credit x -> -x)
This gives you an immutable Checkbook type that you can then use this way:
Checkbook.Empty
|> Checkbook.add (Debit 50.0)
|> Checkbook.add (Credit 25.0)
|> Checkbook.add (Debit 10.0)
|> Checkbook.balance
|> printfn "%A"
Now, back to your problem of storing a mutable list. Well, at some point I will use a class to maintain the state of my application and use a mutable binding. It would look something like that:
type App() =
let mutable cb = Checkbook.Empty
member __.Checkbook with get() = cb
member __.Checkbook with set(value) = cb <- value
I’m quite new at F# myself so this may not be the best possible design but hopefully it will be useful to you… In F#, we try to build a pure functional core and limit side effects to the application boundary. You should search about the onion architecture.
Comments are welcomed!