レコード型のフィールド隠蔽(F#)

例えば下記のようなCounterクラスを考えます。

type Counter() =
    let mutable count = 0
    member this.CountUp()   = count <- count + 1
    member this.CountDown() = count <- count - 1
    member this.Count       = count


これをレコード型を用いて実装すると下記のようになります。

privateを付加することで、外側からフィールドにアクセスできなくなります。

[<AutoOpen>]
module CounterModule =
    type Counter = private { mutable Count : int }
       
    module Counter =
        let create    ()      = { Count = 0 }
        let countUp   counter = counter.Count <- counter.Count + 1
        let countDown counter = counter.Count <- counter.Count - 1
        let count     counter = counter.Count


どちらを利用するか

レコード型を利用したほうが、利用時にF#っぽい記述ができるため、書き方に一貫性が保たれます。

しかしフィールドにmutableが含まれる場合、クラス型のほうを利用したほうが、副作用の場所が差別化され判断しやすくなります。

ほとんどの場合はフィールドがmutableだと考えられる(immutableであれば、ただの変換関数でOKなはず)ので、クラス型の方を利用したほうがよい気がします。