F#中的记录方法

7
我为我的场景编写了一个简单的示例。我创建了一个记录类型Switch
type State =
    | On
    | Off
    with
        member this.flip =
            match this with
            | On -> Off
            | Off -> On

type Switch = { State : State }

然后我写了一个函数,它可以创建一份记录的副本,并将其中一个元素更改。

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

为了连续多次翻转,我写下以下代码:flip
let flipMany times switch =
    [1 .. times]
    |> List.fold (fun (sw : Switch) _ -> flip sw) switch

如果我想将这两个函数作为方法记录下来,那么我应该写成:
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

这样做有什么问题吗?这样做同样有效吗?每次在不同的对象上调用函数sw.flip感觉有点不舒服。

编辑:这只是一个简单的例子,为了解释我的问题。我的问题是如何比较函数flipMany与记录上的flipMany方法。实现可能是天真的,但在这两种情况下是相同的。


2
你不需要通过多次调用flip来实现flipMany - 显然,如果times%2 = 0则不翻转,否则进行一次翻转。 - Gene Belitski
1个回答

15

您的意图可以很简单地实现:

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

在比较静态函数和对象方法的更广泛背景下,惯用的方式是选择函数选项。函数具有显式参数,不应依赖于任何副作用状态,而是基于参数状态生成幂等结果值。相反,对象方法隐含地获得类实例作为参数,并且可能不仅基于参数,还基于其他类字段的状态派生结果值,这与纯函数的幂等属性不一致。

为了更好地感受这种差异,阅读F#组件设计指南并探索F#核心库设计可能会有所帮助。


抱歉我的问题不够清楚,请参见上面的编辑。 - Panos
我明白了,已经相应地调整了答案。 - Gene Belitski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接