如何在 F# 中更新 <T> 类型列表中的值?

How to update values in list of type <T> in F#?

我目前正在学习 F#,与此同时,有点难以掌握受歧视的联合和记录的确切工作原理。

我想知道如何从 <'T> 类型的列表中更新某些值?

我的代码

type Position =
| Location of (int * int)

type Ship = 
{
    Position : Position;
    Projectiles : List<Position>; 
}

我创建了一艘船的实例:

let aShip = 
{
    Position: Location(1,5);
    Projectiles: [Location(1,1);Location(2,5)] 
}

现在,我尝试遍历射弹,但我明白了:

for elem in aShip.Projectiles do
    printfn "%A" elem

// prints out
Location(1,1)
Location(2,5)

但我只想取回值 (1,1) 和 (2,5),我该如何实现?

可以通过提供一个模式解构可区分的联合,其中的一些地方被标识符占据。然后,编译器将生成代码,尝试将此模式与数据匹配,并将数据点绑定到适当的标识符。例如:

let loc = Location (1,2)
let (Location (x,y)) = loc

对于第二行,编译器将生成如下代码:“确保这是一个 Location,然后将第一个 int 绑定到名称 x,然后第二个 int 命名 y"

或者,您可以使用更详细的 match 语法:

let x = match loc with Location(x,y) -> x

对于您的具体情况,这有点矫枉过正,但对于不止一种情况的受歧视联合,match 是处理所有情况的唯一方法,例如:

type Position = 
   | Location of int*int
   | Unknown

let xOrZero = 
   match loc with
   | Location(x,y) -> x
   | Unknown -> 0

以上示例演示了 模式 如何出现在 let 绑定和 match 表达式中,但这还不是全部。在 F# 中,几乎任何您认为是 "variable declaration" 的东西实际上都是一种模式。只是大多数时间模式都是微不足道的,如 let x = 5,但它们不一定是 - 例如let x,y = 5,6

上面的推论是for elem in ...中的elem也是一个模式。这意味着您可以就地解构元素:

for Location(x,y) in aShip.Projectiles do
    printfn "%d,%d" x y

或者,如果您想提取整个对,而不是单独提取 xy,这也是可能的:

for Location xy in aShip.Projectiles do
    printfn "%A" xy