gpt4 book ai didi

design-patterns - F# 命令模式

转载 作者:行者123 更新时间:2023-12-04 22:15:55 26 4
gpt4 key购买 nike

我正在尝试实现命令模式来控制机器人。我正在使用它来探索如何在 F# 中实现命令模式。下面是我的实现:

type Walle(position, rotate) =     
let (x:float,y:float) = position
let rotation = rotate
member this.Move(distance) =
let x2 = distance * sin (System.Math.PI/180.0 * rotation)
let y2 = distance * cos (System.Math.PI/180.0 * rotation)
let newPosition = (x+x2, y+y2)
Walle(newPosition, rotation)
member this.Rotate(angle) =
let newRotation =
let nr = rotation + angle
match nr with
| n when n < 360.0 -> nr
| _ -> nr - 360.0
Walle(position, newRotation)

let Move distance = fun (w:Walle) -> w.Move(distance)
let Rotate degrees = fun (w:Walle) -> w.Rotate(degrees)

let remoteControl (commands:List<Walle->Walle>) robot =
commands |> List.fold(fun w c -> c w)

let testRobot() =
let commands = [Move(10.0);Rotate(90.0);Move(16.0);Rotate(90.0);Move(5.0)]
let init = Walle((0.0,0.0),0.0)
remoteControl commands init

为了提出一个功能解决方案,我选择让机器人的 Action 在每次调用后在其新位置返回一个新的机器人实例(避免突变)。我还使命令函数关闭了执行操作所需的状态。

我很好奇人们在实现该模式时是否认为这些是好的设计决策?或者,如果人们可以就实现该模式提供任何其他建议?

最佳答案

为了避免采用 OO 方式将数据与“类型”中的操作组合并将这种组合表示为“对象”,我的 POV 中更实用的方法是在模块中分别定义数据和操作,如下所示:

module Walle = 
type Walle = {Position : float * float; Rotation : float}

let Move distance (w:Walle) =
let x2 = distance * sin (System.Math.PI/180.0 * w.Rotation)
let y2 = distance * cos (System.Math.PI/180.0 * w.Rotation)
{w with Position = (w.Position |> fst) + x2, (w.Position |> snd) + y2 }

let Rotate angle (w:Walle) =
let newRotation =
let nr = w.Rotation + angle
match nr with
| n when n < 360.0 -> nr
| _ -> nr - 360.0
{w with Rotation = newRotation}

现在您可以创建一个新的 Walle 并使用 |> 函数将其传递给一系列转换 Walle“数据”的函数。这完全是关于数据和对该数据的转换,没有对象:)。它可能不像命令模式,因为它更适合 OO 风格。您真的不需要 FP 中的模式,还是我们?

关于design-patterns - F# 命令模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5892865/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com