Newbie Question about designing with Lists

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 =
    |> List.sumBy (function | Debit x -> x | Credit x -> -x)

This gives you an immutable Checkbook type that you can then use this way:

|> 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! :slightly_smiling_face: