6

我为我的场景写了一个简单的例子。我创建了一个记录类型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每次在不同的对象上调用函数感觉有点不舒服。

编辑:这只是一个简单的例子来解释我的问题。我的问题是如何将函数flipManyflipMany记录中的方法进行比较。实现可能很幼稚,但在这两种情况下都是一样的。

4

1 回答 1

14

您的意图可以简单地实现

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# 核心库设计可能会有所帮助。

于 2012-06-23T20:51:13.393 回答