我为我的场景写了一个简单的例子。我创建了一个记录类型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
方法进行比较。实施可能是天真的,但在两种情况下都是相同的。
答案 0 :(得分:11)
您的意图可以像
一样简单实现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# Components Design Guidelines并探索F# Core libraries design。