Singleton in F#

Singleton, commonly considered to be an anti-pattern, is Object Oriented Pattern that provides single instance of specific type within a process the application is running in. The anti-pattern definition says not to never use such structure, but rather that it should not be overused. The square-wheel problem analogy fits here very well. There may be the cases when the commonly dissuaded solution might be the best.

As I'm exploring Bolero, I've come to the point where I need some sort of store in my application which will persist until I stop the program. The in-memory store. And some may already shout: "Use reddis!"; "Use EF in-memory!"; "Use DI container with singleton registration!"
And I would say "no" to each of them.

I explore Bolero in my off-work time which is already limited. As I know these solution are well tested in IT battlefield, but the installation, configuration and maintenance of each would consume too much of my time. I really don't need such robust solution. What I need is to keep my objects in-memory till my process death and that's it.

And that's where Singleton pattern comes to play.

F#, why so complex?

F# is Functional-First multi-paradigm language. Doing OOP in F# is possible, but man, with what cost? The non-idiomatic level when defining class members, constructor and so-on, is damn high.

The motivation of this post comes from the struggle I'd like to avoid in future when I'd need to create singleton in F# again.

This is Singleton class which encapsulates RequestedRelease collection.

type ReleaseStore private(requests) =                      // 1
    let releases: ResizeArray<RequestedRelease> = requests // 2
    member this.Requests with get () = requests            // 3
    static member val Instance =                           // 4
        let arr = new ResizeArray<RequestedRelease>()      // 5
        ReleaseStore(arr)                                  // 6
  1. Define class ReleaseStore with private constructor accepting requests as argument. The type of the argument will be inferred later by argument usage, but if you like things more explicit, you can declare the type like that: private(requests: ResizeArray<RequestedRelease>)
  2. Declare private, immutable field inside the class. Here we declare type explicitly and assign the constructor argument to our field.
  3. Declare public getter Releases which will be available on class instance. The getter returns requests field we declared in previous line.
  4. Declare static field which's value will be set by static constructor.
  5. Create empty RequestedRelease collection. The ResizeArray is an F# alias for System.Collections.Generic.List<>.
  6. Create new instance of ReleaseStore which will be set to the static Instance value.

The value RequestedRelease collection will be initialized only once, when we reference the Instance field for the first time. Every next time we'll be referencing the same collection.

let request = { title = "Die Hard" }

printfn "ReleaseRequests count: %d" ReleaseStore.Instance.Requests.Count

The singleton pattern will perfectly fit my needs while prototyping simple Bolero App. When the time comes, I'll replace it with disk-persisted store. The library I'll use is just yet another implementation detail ;)

comments powered by Disqus