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

Dev*_*ard 3 f# records discriminated-union

我目前正在研究F#,同时,有点努力想要了解歧视的工会和记录究竟如何运作.

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

我的代码

type Position =
| Location of (int * int)

type Ship = 
{
    Position : Position;
    Projectiles : List<Position>; 
}
Run Code Online (Sandbox Code Playgroud)

我创建了一个船的实例:

let aShip = 
{
    Position: Location(1,5);
    Projectiles: [Location(1,1);Location(2,5)] 
}
Run Code Online (Sandbox Code Playgroud)

现在,我试图绕过弹丸,但我明白了:

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

// prints out
Location(1,1)
Location(2,5)
Run Code Online (Sandbox Code Playgroud)

但我只想得到值(1,1)和(2,5),我将如何实现这一目标?

Fyo*_*kin 5

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

let loc = Location (1,2)
let (Location (x,y)) = loc
Run Code Online (Sandbox Code Playgroud)

对于第二行,编译器将生成代码,以" 确保这是一个Location,然后将第一个int绑定到name x,第二个int 绑定到namey "

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

let x = match loc with Location(x,y) -> x
Run Code Online (Sandbox Code Playgroud)

对于您的具体情况,这是过度的,但对于具有多个案例的受歧视的工会,match是处理它们的唯一方法,例如:

type Position = 
   | Location of int*int
   | Unknown

let xOrZero = 
   match loc with
   | Location(x,y) -> x
   | Unknown -> 0
Run Code Online (Sandbox Code Playgroud)

上面的例子演示了模式如何出现在let-bindings和match表达式中,但这不是全部.在F#中,几乎所有你认为是"变量声明"的东西实际上都是一种模式.这只是大部分时间模式都是微不足道的let x = 5,但是它们不一定是 - 例如let x,y = 5,6

从上述的必然结果是,elemfor elem in ...图案.这意味着您可以对元素进行结构化:

for Location(x,y) in aShip.Projectiles do
    printfn "%d,%d" x y
Run Code Online (Sandbox Code Playgroud)

或者,如果你想提取对作为一个整体,而不是xy个别,这也是可能的:

for Location xy in aShip.Projectiles do
    printfn "%A" xy
Run Code Online (Sandbox Code Playgroud)