Record methods in F#
Asked Answered
B

1

7

I have written a simple example for my scenario. I create a record type Switch

type State =
    | On
    | Off
    with
        member this.flip =
            match this with
            | On -> Off
            | Off -> On

type Switch = { State : State }

and then I write a function that creates a copy of the record with one element changed

let flip switch = { switch with State = switch.State.flip } 

To flip many successive times I write

let flipMany times switch =
    [1 .. times]
    |> List.fold (fun (sw : Switch) _ -> flip sw) switch

If I want put these two functions on the record as methods, I write instead

type Switch =
    { State : State }
    member this.flip = 
        { this with State = this.State.flip }
    member this.flipMany times =
        [1 .. times]
        |> List.fold (fun (sw : Switch) _ -> sw.flip) this

Is there anything wrong with doing this? Is it equally efficient? It feels a bit uncomfortable calling the function sw.flip on a different object every single time.

Edit: this is just a simple example in order to explain my question. My question is on how the function flipMany compares with the flipMany method on the record. The implementation might be naive, but it is the same in both of cases.

Bartholomew answered 23/6, 2012 at 19:23 Comment(1)
You do not need implementing flipMany thru multiple calls to flip - apparently times%2 = 0 means do not flip, otherwise do one flip.Diadem
D
15

Your intent can be implemented as simple as

let flipMany times switch =
    match (times % 2) with
    | 1 -> { switch with State = switch.State.flip }
    | _ -> switch

type Switch =
    { State : State } 
    member this.Flip = { this with State = this.State.flip }
    member this.FlipMany times =
        match (times % 2) with | 1 -> this.Flip | _ -> this

In the broader context of comparing a static function versus an object's method the idiomatic way would be sticking to function option. A function has explicit arguments and must not depend on any side state, but state of arguments, to produce an idempotent result value. On the contrary, an object method implicitly gets an instance of the class as an argument and may derive result value not just from arguments, but based on the state of other class fields too, which is not in line with idempotency property of a pure function.

To feel this difference better it may help reading thru F# Components Design Guidelines and exploring F# Core libraries design.

Diadem answered 23/6, 2012 at 20:51 Comment(2)
Sorry if my question was not clear, please see the edit above.Bartholomew
I see; adjusted the answer accordingly.Diadem

© 2022 - 2024 — McMap. All rights reserved.